MySQl 面试重点_6.MySQL 锁机制总结
一, 锁概述
锁是计算机协调多个进程或线程并发访问某一资源的机制。

二, 锁的分类
- 按照对数据的操作类型分为: 读锁, 写锁;
-)))))))))))))))))))))))))))))))))))))))))))) - 按照对**数据的操作力度(锁的粒度)**分为: 表锁, 行锁;
- 按照对待锁的态度分为悲观锁, 乐观锁;
2.1 从数据的操作类型角度分为: 读锁和写锁
读锁:
又称为共享锁(Share Lock), 针对同一份数据, 多个读操作可以同时进行而不会相互影响;
写锁:
又称为排他锁(Exclusive Lock), 当前写操作没有完成前, 它会阻断其他写锁和读锁;
- 对于InnoDB引擎, 读锁和写锁既可以加在表上, 也可以加在行上;

2.2 从数据的操作力度(锁的粒度)角度分为: 表锁和行锁, 页锁
为了尽可能提高数据库的并发度,每次锁定的数据范围越小越好,理论上每次只锁定当前操作的数据的方案会得到最大的并发度,但是管理锁是很耗资源的事情(涉及获取、检查、释放锁等动作)。因此数据库系统需要在高并发响应和系统性能两方面进行平衡,这样就产生了“锁粒度(Lock granularity)”的概念。
对一条记录加锁影响的也只是这条记录而已,我们就说这个锁的粒度比较细;其实一个事务也可以在表级别进行加锁,自然就被称之为表级锁或者表锁,对一个表加锁影响整个表中的记录,我们就说这个锁的粒度比较粗。锁的粒度主要分为表级锁、页级锁和行锁。
A. 表锁:
该锁会锁定整张表,它是MysQL中最基本的锁策略,并不依赖于存储引擎(不管你是MySQL的什么存储引擎,对于表锁的策略都是一样的),并且表锁是开销最小的策略(因为粒度比较大)。由于表级锁一次会将整个表锁定,所以可以很好的避免死锁问题。当然,锁的粒度大所带来最大的负面影响就是出现锁资源争用的概率也会最高,导致并发率大打折扣。
- 偏向MyISAM存储引擎, 开销小, 加锁快;
- 锁定力度大, 发生所锁冲突的概率最高, 并发度最低;

a. 意向锁
意向锁存在的意义:
- 如果没有意向锁的话,则需要遍历所有整个表判断是否有行锁的存在,以免发生冲突
- 如果有了意向锁,只需要判断
该意向锁与即将添加的表级锁是否兼容即可。因为意向锁的存在代表了,有行级锁的存在或者即将有行级锁的存在。因而无需遍历整个表,即可获取结果.

解释: 参见本文
b. 自增锁(AUTO-INC)
c. 元数据锁(MDL)

B. 行锁:
开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
a. 记录锁(Record Locks)

b. 间隙锁(Gap Locks)

c. 邻键锁(Next-Key Locks)

临键锁集合了记录锁的锁住某条记录以及 间隙锁的锁住记录附近的范围 两种功能;
Q: InnoDb行锁到底锁的是什么?

综上所述:
- InnoDB的行锁是通过给索引上的索引项加锁来实现的,只有通过索引条件进行数据检索,Innodb才使用行级锁。否则,将使用表锁(锁住索引的所有记录)。
- 借此我们是不是能联想到,如果我们的删除/修改语句是没有命中索引的,哪么,则会锁住整个表,这在性能上的影响还是挺大的
2.3 从对待锁的态度划分为: 乐观锁和悲观锁
从对待锁的态度来看锁的话,可以将锁分成乐观锁和悲观锁,从名字中也可以看出这两种锁是两种看待数据并发的思维方式 。需要注意的是,乐观锁和悲观锁并不是锁,而是锁的设计思想
A. 悲观锁(Pessimistic Locking)

B. 乐观锁

悲观锁和乐观锁的使用场景

二, 使用: 读锁/共享锁(S)与写锁/排它锁(X)
2.1 共享锁
共享锁又称之为读锁, 简称s锁, 顾名思义就是
多个事务对于同一数据可以共享一把锁, 都能够访问到数据库,但是只能读不能修改
#加锁方式
select * from users where id = 1 lock in share mode;
#释放方式(即回滚或提交)
rollback/commit;
- 举例:

2.2 排它锁
排它锁又称为写锁, 简称X锁,
排它锁不能与其他锁并存, 如一个事务获取了一个数据行的排它锁, 其他事务就不能再获取该行的锁(包括共享锁和排它锁), 只有当前获取了排它锁的事务可以对数据进行读取和修改(此时其他事务要读取数据可从快照获取)
#加锁方式
delete update insert 默认加了排它锁
select * from users where id = 1 for update;
#释放方式(即回滚或提交)
rollback/commit;
- 举例:

三, 验证: 意向共享锁(IS)和意向排他锁(IX)

四, 行锁的算法

行锁算法举例:

五, 总结
MySQL 的 Innodb引擎正是通过上述不同类型的锁,完成了事务隔离:
加 X 锁 避免了数据的脏读
加 S 锁 避免了数据的不可重复读
加上 Next Key 避免了数据的幻读
- 参考文章: https://mp.weixin.qq.com/s?__biz=MzI1Mzg4OTMxNQ==&mid=100000550&idx=1&sn=8a5cdff008fc1eed7b5c623c1bdf4ed1&chksm=69ccdd6a5ebb547c7b7baf6be78763fc5065e0a58de202f3e25d8d8ed56e6d1c1146332cfec1#rd


浙公网安备 33010602011771号