MySQL高级9-锁

MySQL,高级 · 浏览次数 : 146

小编点评

## 7. 意向锁介绍 7.1 意向锁介绍 为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每一行数据是否加锁,使用意向锁来减少表锁的检查。 ## 7.2 意向锁查询select object_schema, object_name, index_name, lock_type, lock_mode, lock_data from performance_schema.data_locks 7.3 意向锁案例 说明1:客户端1开始事务,并执行查询语句,客户端2锁的情况,显示为空表 说明2:客户端执行查询语句,并手动添加共享,在客户端2中,查询lock_mode字段中有一个S,即共享锁 说明3:客户端2也手动开启了一个共享锁,并且成功,说明共享锁与共享锁之间是兼容的 说明5:在客户端2上执行更新id=2的数据成功,并且查询可以看出,自动增加了一个(X)排它锁 说明6:  因为更新id=2的数据时,id=2的这一行上没有其他的锁,所以可以执行成功 说明7:因为在客户点1上已经对id=1的行上添加了一个共享锁(S), 这是客户端2对id=1的数据做update操作时会自动在id=1的数据上在添加一个排它锁(X),这是id=1的数据上就会有共享锁(S)和排它锁(X),又因为共享锁和排它锁不兼容,所以在update id = 1 的时候就会阻塞,需要等到共享锁(S)释放了,才能执行成功 ## 7.4 行锁案例 说明1:客户端1开始事务,并执行查询语句,客户端2锁的情况,显示为空表 说明2:客户端执行查询语句,并手动添加共享,在客户端2中,查询lock_mode字段中有一个S,即共享锁 说明3:客户端2也手动开启了一个共享锁,并且成功,说明共享锁与共享锁之间是兼容的 说明4:默认情况下,InnoDB在 repeatable read 事务隔离级别运行,InnoDB使用next-key 锁进行搜索和索引扫描,以防止幻读 ## 7.5 间隙锁/临建锁 9.1 默认情况下、InnoDB在 repeatable read 事务隔离级别运行,InnoDB使用next-key 锁进行搜索和索引扫描,以防止幻读 9.2 索引上的等值查询(唯一索引),会访问到不满足条件的第一个值为止 9.3 索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁 9.4 索引上的范围查询(唯一索引),会访问到不满足条件的第一个值为止 注意:间隙锁唯一的目的是防止其他事务插入间隙,间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事物在同一间隙上采用间隙锁

正文

一、简介

  锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除了传统的计算资源(CPU、RAM、i/O)的挣用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素,从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。

 

二、分类

  MySQL中的锁、按照锁的粒度分,分为以下三类

  • 全局锁:锁定数据量的所有表
  • 表级锁:每次操作锁住整张表
  • 行级锁:每次操作锁住对应的行数据

 

三、全局锁

  3.1 简介

    全局锁就是对整个数据库实例枷锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,以及更新操作的事物提交语句都会被阻塞,其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。

  3.2 添加全局锁语法 

flush tables with read lock;

  3.3 打开全局锁语法

unlock tables;

  3.4 案例一

  

    说明1:客户端1中设置了全局锁

    说明2:客户端2中,执行查询语句正常的,但是执行DML语句中的更新操作却是处于阻塞状态

  3.5 案例二

  

    说明1:客户端1中设置了全局锁

    说明2:客户端3中做了数据库备份的语句,其中mysqldump是和mysql一样由MySQL服务器提供的数据库备份的命令

    说明3:当数据库设置了全局锁的时候,不影响数据库的备份

    说明4:MySQL备份实在终端命令行模式下,不是在数据库命令模式下,注意!注意!注意!

  3.6 案例三

  

    说明1:客户端1释放全局锁 

    说明2:客户端2的更新语句马上执行成功

    说明3:通过客户端2的更新语句的执行时间37min,可以说明该语句被客户端1的全局锁,阻塞了37分钟

  3.7 全局锁特点

    数据库中加全局锁,是一个比较重的操作,存在以下问题

    • 如果在主库上备份,那么在备份期间都不能执行更新,业务上基本就是停摆状态
    • 如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟

    在innoDB引擎中,我们可以在备份时加上 --single-transaction 参数来完成不加锁的一致性数据备份

 

四、表级锁

  4.1 简介

    表级锁,每次操作锁住整张表,锁定粒度大,发生锁冲突的概率最高,并发度最低,应用在MyISAM,InnoDB等存储引擎中

  4.2 表级锁的分类

    • 表锁
    • 元数据锁(meta data lock, MDL)
    • 意向锁

五、表锁

  5.1 表锁的分类

    • 表共享读锁(read lock)
    • 表独占写锁(write lock)

  5.2 表锁语法

    加锁:lock tables 表名... read/write

    释放锁:unlock tables / 客户端断开连接

    说明1:加锁的时候,可以多张表同时加锁

    说明2:客户端断开连接也能释放表锁

  5.3 读锁案例

      

   

      说明1:当对一个表添加读锁,不会影响其读取数据,但是会影响其新增,修改,删除的操作语句

    说明2:当对一个表添加读锁,不会影响其他客户端读取数据,但是会让其他客户端的新增,修改,删除等操作语句处于阻塞状态。

    说明3:当把锁释放了,自己及其他客户端的新增,删除和修改语句才会结束阻塞。

  5.4 写锁案例

    

    

    说明1:添加写锁的客户端可以正常对表进行查询和增删改等操作

    说明2:其他客户端的查询,修改,新增,删除都操作在有写锁的情况下,都要处于阻塞状态,直到其添加写锁的客户端释放写锁。

    说明3:上图中的修改等应该是DML语句(Data Manipulation Language 数据操作语言,用来对数据库表中的数据进行增删改的),不是DDL语句(DDL: Data Definition Language 数据定义语言,用来定义数据库对象,数据库,表,字段)

 

六、元数据锁

  6.1 元数据锁简介:

    元数据锁(meta data lock):简称 MDL

    MDL加锁过程是系统自动控制,无需显示使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作,为了避免DML和DDL冲突,保证读写的正确性

  6.2 元数据锁的类型

    在MySQL5.5 中引入了MDL, 当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更操作的时候,加MDL写锁(排他)

    

  6.3 案例

    

    说明1:select 和 update 分别会添加SHARED_READ 和 SHARED_WRITE, 但是SHARED_READ 和 SHARED_WRITE是兼容的,所以其他客户端是可以做更删改查的

    

     说明2:alter table 会产生EXCLUSIVE 锁。该锁与其他MDL都互斥。ß

  6.4 查看元数据锁

select object_type,object_schema,object_name,lock_type,locak_duration from  performance_schema.metadata_locks;

    

 

七、意向锁

  7.1 意向锁介绍

    为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每一行数据是否加锁,使用意向锁来减少表锁的检查。

    情况1:不加意向锁

   

    说明1:线程A 开启一个事务,并且使用DML语句更新数据,此时会对更新的数据添加行锁,

    说明2:此时线程A 的事务并没有提交事务,线程B又对该表添加一个表锁,此时添加表锁的时候,就会从第一条数据,依次检查到最后一条数据,看是否有其他的锁,如果有其他锁,需要等到其他锁释放了,才能执行添加表锁

    说明3:此时添加表锁的效率就非常低  

    情况2:加意向锁

   

    说明4:当线程A 开启了一个事务,并且执行了DML的更新数据的语句,此时除了会给该行数据添加行锁之外,还会添加一个基于整表的意向锁。

    说明5:当线程B 再次添加表锁的时候,就不用逐行排查是否有行锁了,而是直接检查整表是否有意向锁,如果意向锁和表锁兼容则直接加表锁

    说明6:如果表锁和意向锁不兼容,则仍然会等到意向锁释放了,表锁才能添加成功。

  7.2 意向锁的类型

    • 意向共享锁(IS): 由语句 select ... lock in share mode 添加。与表锁共享锁(read)兼容,与表锁排它锁(write)互斥。
    • 意向排它锁(IX): 由 insert, update, delete, select ... for update 添加。  与表锁共享锁(read)及排它锁(write)都互斥,意向锁之间不会互斥

  7.3 意向锁查询

select object_schema, object_name, index_name, lock_type, lock_mode, lock_data from performance_schema.data_locks;

  7.4 意向锁案例

    

    说明1:客户端1开启事务,并且查询语句时设置一个意向共享锁(IS)

    说明2:客户端2在客户端1的事务未提交的时候,创建read锁成功

    说明3:意向共享锁(IS)和read共享锁兼容

    

    说明4:执行update等DML语句时,MySQL会自动添加行锁和排他意向锁。

    

    说明5:排他意向锁与共享read锁和排他write锁都互斥

    说明6:意向锁的作用主要是解决行锁和表锁之间的矛盾。

 

八、行级锁

  8.1、简介

    行级锁,每次操作锁住对应的行数据,所得粒度最小,发生锁冲突的概率最低,并发度最高,应用在InnoDB存储引擎中

    InnoDB的数据是基于索引组织的行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁,对于行级锁,主要分为一下三类

    1、行锁(record lock): 锁定单个行记录的锁,防止其他事务对此行进行update和delete,在read committed和repeatable read隔离级别下都支持。

    

     2、间隙锁(Gap lock): 锁定索引记录间隙(不包含记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读,在repeatable read隔离级别下支持

     

     3、临建锁(Next-Key lock): 行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙,在repeatable read隔离级别下支持

     

   8.2 行锁

    InnoDB 实现了一下两种类型的行锁

    1、共享锁(S): 允许一个事物去读一行,阻止其他事务获得相同数据集的排他锁。

    2、排他锁(X): 允许获取排他锁的事务更新数据,阻止其他事物获得相同数据集的共享锁和排他锁

    

     3、不同语句的枷锁情况

    

     4、默认情况下,InnoDB在 repeatable read隔离级别下运行,InnoDB使用next-key锁进行行搜索和索引扫描,以防止幻读

    • 针对唯一索引进行检索时,对已经存在的记录进行等值匹配时,将会自动优化为行锁
    • InnoDB的行锁是针对于索引加的锁,不通过索引检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁

   8.3 行锁案例

    

    说明1:客户端1开始事务,并执行查询语句,客户端2锁的情况,显示为空表

    说明2:客户端执行查询语句,并手动添加共享,在客户端2中,查询lock_mode字段中有一个S,即共享锁: 

    

    说明3:客户端2也手动开启了一个共享锁,并且成功,说明共享锁与共享锁之间是兼容的。

    

    说明5:在客户端2上执行更新id=2的数据成功,并且查询可以看出,自动增加了一个(X)排它锁。

    说明6:  因为更新id=2的数据时,id=2的这一行上没有其他的锁,所以可以执行成功

    说明7:因为在客户点1上已经对id=1的行上添加了一个共享锁(S), 这是客户端2对id=1的数据做update操作时会自动在id=1的数据上在添加一个排它锁(X),这是id=1的数据上就会有共享锁(S)和排它锁(X),又因为共享锁和排它锁不兼容,所以在update id = 1 的时候就会阻塞,需要等到共享锁(S)释放了,才能执行成功。

    

    说明8:排它锁X 与 排它锁X 也是不兼容的。

    

     说明9:InnoDB的行锁是针对于索引加的锁,不通过索引检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁

    

     说明10:根据业务需要,尽量使用索引当所查询条件,既快又减少阻塞。

 

九、间隙锁/临建锁

  9.1 默认情况下、InnoDB在 repeatable read 事务隔离级别运行,InnoDB使用next-key 锁进行搜索和索引扫描,以防止幻读。

    

  9.2 索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁

    

  9.3 索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁

    

    说明1:非唯一索引,即普通索引,在做等值查询的时候,会添加三把锁

    说明2:在查询的当条记录上添加一个共享锁,允许其他事务继续查询该记录

    说明3:通过标注6的位置,lock_type 为S,REC_NOT_GAP 说明同时给这一行添加一个行锁

    说明4:通过标注7的位置,lock_type 为 S,GAP 说明在第一个不满足查询数据的前面也会加一个间隙锁。其目的是为了防止在select 查询的时候,其他事务去往这个索引之前插入或者修改数据,这样查询就会出现幻读的现象。

  9.4 索引上的范围查询(唯一索引),会访问到不满足条件的第一个值为止。

    

  注意:间隙锁唯一的目的是防止其他事务插入间隙,间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事物在同一间隙上采用间隙锁 

与MySQL高级9-锁相似的内容:

MySQL高级9-锁

一、简介 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除了传统的计算资源(CPU、RAM、i/O)的挣用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素,从这个角度来说,锁对

MySQL高级

前言: 本篇文章是本人学习MySQL高级的笔记。 资料:《MySQL是怎样运行的》、《小林Coding-图解MySQL》、《MySQL45讲》、《尚硅谷康师傅MySQL视频》 一、基础篇 1. 什么是关系型数据库? 关系型数据库是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,一系列的

MySQL高级1-存储引擎

一、Mysql体系结构 1.1、连接层 最上层是一个客户端和链接服务,主要完成一些类似于链接处理,授权认证,及相关的安全方案,服务器也会为安全接入的而每个客户端验证它所具有的操作权限 1.2、服务层 第二层架构主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化,部分内置

【转帖】《MySQL高级篇》四、索引的存储结构

1. 为什么使用索引 假如给数据使用 二叉树 这样的数据结构进行存储,如下图所示 2、索引及其优缺点 2.1 索引概述 2.2 优点 类似大学图书馆建书目索引,提高数据检索的效率,降低 数据库的 IO 成本 这也是创建索引的主要的原因。通过创建唯一索引,可以保证数据库表中每一行 数据的唯一性 (唯一

MySQL 高级(进阶) SQL 语句

MySQL 高级(进阶) SQL 语句 use gy; create table location (Region char(20),Store_Name char(20)); insert into location values('East','Boston'); insert into loc

MySQL高级2-SQL性能分析

一、SQL执行频率 MySQL客户端 连接成功后,通过show [session | global] status 命令可以提供服务器状态信息,通过如下指令,可以查看当前数据库的insert,update,dalete,select的访问频次 show [global | session] stat

MySQL高级3-索引的结构和分类

一、索引概述 1.1 索引的介绍 索引index:是帮助 Mysql 高效获取数据 的 有序的数据结构,在数据之外,数据库系统维护着的满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引 1.2 索引的优缺点 优点1:提

MySQL高级4-索引的使用规则

一、最左前缀法则 如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列,如果跳跃某一列,索引将部分失效(后面的字段索引失效) 示例1:account_transaction表中创建一个联合索引,使用method字段+trader_staff_

MySQL高级5-SQL优化

一、插入数据优化 1.1 批量插入 如果有多条数据需要同时插入,不要每次插入一条,然后分多次插入,因为每执行一次插入的操作,都要进行数据库的连接,多个操作就会连接多次,而一次批量操作只需要连接1次 1.2 手动提交事务 因为Mysql默认每执行一次操作,就会提交一次事务,这样就会涉及到频繁的事务的开

MySQL高级6-视图

一、视图介绍 视图(View):是一种虚拟存在的表,视图中的数据并不在数据库中实际存在,行和列数据来自,定义视图时查询使用的表,并且是在使用视图时动态生成的。通俗的讲,视图只保存了查询的SQL逻辑,不保存查询的结果。 二、创建视图 2.1 语法 create [or replace] view 视图