Mysql锁学习分析总结

1.首先,先了解一下mysql中有哪些锁?锁的划分?

按照锁的粒度分
全局锁:锁整个数据库,由mysql Server层实现(分为mysql server层和存储引擎层)
表级锁:锁某个表,有mysql Server层实现
行级锁:锁某行数据,由存储引擎实现(比如InnoDB).
按照锁功能分:共享锁(读锁)和排它锁(写锁)。
按照锁实现方式分:悲观锁(java中的synchorized)和乐观锁(java中的cas)

表级锁和行级锁区别
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;

1.1表锁

查看表锁

show status like '%table_locks%'

table_locks_immediate:产生表锁的次数;
table_locks_waited:因表锁而发生等待的次数;

表锁分为:表共享读锁和表独占写锁
表共享读锁:session1对test表加了读锁,session1和session2都能读;session1执行修改删除操作会报错;session2执行修改删除会一直等待;并且session1当前不能查询除test以外的表。
表独占写锁:只当当前加锁的session才能增删改查,其它session任何操作都不行,会阻塞。

锁表语句:

lock table test read/write;
1.2行锁

mysql的行级锁是由存储引擎实现的,以下主要说InnoDB实现的行级锁。
行锁按锁范围分为
记录锁:锁定索引中的一条记录
间隙锁:要么锁住索引记录中间的值,要么锁住第一个索引记录前面的值或者最后一个索引记录后面的值。
Next-Key Locks:是记录锁和间隙锁的组合。

行锁按功能分为共享锁和排它锁(insert,update,delete);
InnoDB不会对select语句加锁
可以显示的加锁

select * from test LOCK IN SHARE MODE  (共享锁)
select * from test for update (排它锁)

InnoDB行锁是通过给索引上的索引项加锁来实现的,因此只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
innoDB也实现了表级锁(意向锁):意向共享锁(IS)和意向排他锁(IX),主要作用是为了全表更新数据时提升性能,不然在全表更新之前还需要检查记录上是否有行锁。

检查innoDB行级锁情况:

show status like 'innodb_row_lock%'

Innodb_row_lock_time_avg(等待平均时长)
Innodb_row_lock_waits(等待总次数)
Innodb_row_lock_time(等待总时长)这三项。

1.3mysql innoDb引擎是怎么加行锁的

mysql具体怎么加锁跟你的条件是否用了索引,索引的类型,事务的隔离级别有关。
下面我们主要以一个例子说明一种情况:
select * from test where name=“fay” for update;(id为主键)
后面加上了for update表示当前读(读取最新数据),name字段有索引,不是唯一索引,
1.当前隔离级别是RC(读已提交):先通过索引找到name="fay"的B+树节点(加行锁是对索引节点加锁,条件字段必须要有索引),由于不是唯一索引,索引可能有多条,对找到的节点加排它锁(节点对应的节点值为主键),然后再找到对应的主键节点,给主键节点加上排它锁。这样为什么不能解决幻读呢?(能解决不可重复读,因为用了for update)
2.当前隔离级别是RR(可重复读):在RC的过程中还多了一步,就是加上了间隙锁,因为索引是有序的,只要将可能插入name="fay"的节点空隙给锁了(间隙锁),在查询期间,就不会有新的记录插入,也就解决了幻读

下面说明一下什么是幻读:以上面的查询语句说明,第一次name="fay"的只有三条,在第二次查询时确有五条,这就是幻读。

以此情况为基础,大家可以自己想想还有那些情况,不同的索引类型组合不同的隔离级别,会有很多种情况。

发布了42 篇原创文章 · 获赞 29 · 访问量 2522

猜你喜欢

转载自blog.csdn.net/qq_32314335/article/details/103860344