Intro
为什么需要锁?
锁是避免并发情况下的数据安全问题,广泛应用于各种系统中。
Mysql 锁的种类
innodb使用的行级锁,即便一些情况下,innodb发生了锁“表”,这里的锁表,其实是锁“全部行”。而myisam使用的是表级锁。二者的区别如下:
- 全局锁: 整个数据库的全部实例加上锁
- 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
- 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
- 页级锁:页是粒度更小的存储单位,容易出现死锁;
全局锁
- 【作用】顾名思义,全局锁就是对整个数据库实例加锁。MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令。
- 【应用场景】做全库逻辑备份。也就是把整库每个表都 select 出来存成文本。
- 例如进行数据备份或者迁移的时候,先开启全局锁,那么此时业务不能写入。不过最好评估下中断的时间。
表级锁
一种是表锁,一种是元数据锁(meta data lock, MDL)。
表锁
- 【怎么开启】需要手动开启表锁,会限制所有线程的写操作,包括自己的线程。(语法: lock tables ... read/write)
元数据锁:
不需要显式使用, Mysql 5.5 引入MDL, 单需要对一个表结构进行变更的时候,就加入一个MDL写锁, 如果只是增删改查, 就加入一个MDL写锁。
- 【种类】MDL 读锁 和 排他锁
- 【作用】 MDL是防止DDL 和 DML的冲突(写锁与其他锁不兼容, 读锁与读锁兼容)
行级锁
读写锁
-
读锁: Lock In Share mode 所有的读都有这个S锁;
- select 的操作默认下会加上Lock in share mode的小尾巴,如select * from t where id = 1 ,实际上执行的是select * from t where id = 1 lock in share mode
-
写锁: FOR UPDATE 所有更新操作都有这个X锁;
-
update 的操作默认情况下会加上FOR UPDATE的小尾巴
-
意向锁
-
IX: 标志着表里有数据被行锁 锁住
-
IS: 标志着表里有数据被读锁 锁住