锁
保护数据在高并发情况下可靠的对象
按照粒度分: 全局锁:锁定所有表 表级锁:锁定整张表 行级锁:锁定对应的行
全局锁
对整个数据库加锁,整个数据库处于制只读状态,DML和DDL语句在执行中,都将处于阻塞状态,只有DQL可以执行。
典型的操作是做全库的逻辑备份,对所有的表进行锁定,获取一致性的视图,保证数据的可靠性 下面对备份情况做一个示例
# 加锁
flush tables with read lock ; -- 全局锁加锁
# 备份
mysqldump -u 用户名 -p 密码 数据库名称 >数据库名称.sql
# 该指令会将数据库备份到数据库.sql中
# 解锁
unlock tables ;这玩意不适用于中文名(?
缺点
缺点很明显了 如果在主库备份,业务基本暂时GG 如果在从库备份,从库不能及时同步主库,容易造成主从不一致
解决
在 InnoDB 引擎中,我们可以在备份时加入参数 --single-transaction 来实现不加锁完成备份
mysqldump --single-transaction -u 用户名 -p 密码 数据库名称 >数据库名称.sql表级锁
对整张表加锁,整张表处于制只读状态,DML和DDL语句在执行中,都将处于阻塞状态,只有DQL可以执行。 粒度大,发生冲突概率高,并发度低,应用在MyISAM,InnoDB,BDB存储引擎
主要分为:表锁,元数据锁 (Meta data lock),意向锁。
表锁
分为:表共享读锁,表独占写锁
# 加锁
lock tables table_name read/writer;
# 解锁
unlock tables; \ 关闭客户端表共享读锁: 自己可以读,自己不可以写。别人可以读,别人不可以写 表独占写锁: 自己可以读,自己可以写,别人不可以读,别人不可以写 (太屌了
元数据锁 (Meta data lock)
元数据是什么呢?元数据可以简单理解为就是表结构,如果这张表有尚未提交的事务,那么就不能对表结构,也就是元数据进行修改。 MDL由系统自动控制,无须显式调用,在访问的时候就会自动加上,用于维护数据一致性。为了规避DML和DDL的冲突
MySQL在5.5引进了MDL,在执行增删改查的时候,加入MDL读锁(共享锁)在修改元数据(表结构)时,加入MDL写锁(排他锁)
加锁类型:

DDL,DQL,DCL在执行时系统都会对其进行加锁,但是DDL修改了元数据,导致其锁是独享的,也就是说,DDL在执行时,DQL和DCL都不能执行。DQL和DCL在执行时,DDL不能执行。,因为增删改查的过程中禁止元数据被修改。
意向锁
在一个行级锁被加载之后,表级锁就不能添加了,表级锁在添加时需要扫描整张表,如果全部的行都没被加锁,表级锁就可以加锁。反之不能加锁。但是这样效率太低了,所以我们发明了意向锁,在任意一个行级锁被加载的时候,意向锁也被加载了,这样,表级锁在被加载之前就只用扫描意向锁就可以判断整张表有没有行锁被加载,大大的提高了效率。
意向共享锁(IS):和表兼容锁兼容,和表排它锁互斥 意向排他锁(IX):和表锁互斥,和意向锁兼容
# 查看意向锁加锁情况
select object_schema,object_name,index_name,lock_data,lock_mode,lock_data
from performance_schema.data_locks;行级锁
对整行加锁,整行处于制只读状态,DML和DDL语句在执行中,都将处于阻塞状态,只有DQL可以执行。 锁粒度最小,发生锁冲突概率低。并发度高,应用在InnoDB中 InnoDB基于索引组织的,行级锁是通过对索引项的加锁实现的
行级锁分为三类:行锁,间隙锁,临间锁
行锁
防止事务对其进行delete和update操作,在RC,RR都支持
分为两种: 共享锁(S):允许其他事务获取共享锁,不允许其他事务获取本行的排它锁; 排它锁(X):阻止其他事务获取S和X;
行锁加锁类型:

那么就诞生了一个问题,如果是通过索引精确的对一行数据进行操作,那么可以加行锁,因为其他行的数据一定不会用到,但是如果不能通过索引精确的锁定被操作行,这时候,行锁就会升级为行锁,降低性能
间隙锁/临间锁
因为二者功能有相同的地方,放在一起写
间隙锁:锁住B+树下链表的数据间隙,防止Insert对其进行操作,产生幻读,在RR支持 临间锁:锁住数据和他前面的间隙Gap,在RR级别支持
1:通过唯一索引进行等值查询,给不存在的记录加锁,就会优化为间隙锁 假如ID行从4直接跳到了10,那么对7进行操作,会直接锁住5-9的空间,此时,对6的加锁操作将会被阻塞,间隙锁会对整个间隙进 行加锁。 2:通过普通索引进行的等值查询,向右遍历,直到不满足条件时,对这段间隙加间隙锁 因为普通索引并不是唯一的,在加锁查询时,可能会有相同的索引被添加,如果这个时候被添加了,其他的事务再查询只能查询到刚 刚被添加的索引,会产生错误,因此系统会向前加锁间隙,向后寻找第一个不符合查找条件的索引之前的间隙进行加锁,防止相同的 索引插入 3:唯一索引上面的范围查询也会被加上临间锁 和上面的情况一样,符合条件的是一个范围,如果这个范围内部有新的索引被插入,就会引起数据的不可靠。 假如ID从4开始,我们查询ID大于4的时候,就会加一个从四开始到正无穷的临间锁,因为这个范围都被查询了,这个范围内部也不 允许有索引插入