关于mysql锁的学习

锁的类型: 表锁、页锁、行锁、间隙锁【读锁(共享锁)、写锁(排他锁)】、乐观锁、悲观锁(晕,其实没这么多东西)

mysql.INNODB_LOCKS 这张表记录了发生了锁争用的信息;虽然一个事务正在加了一些锁,如果没有其它session等待这些锁的话,这个表里面也是查不到的哦

但是,A表正在事务中被更新时,如果:

lock tables A write;

虽然被阻塞,但是 mysql.INNODB_LOCKS里面却查不到任何记录!  (why: lock tables 不是存储引擎级别的锁)

 

实例分析:

表结构:

sql语句1:

sql语句2:

如果简单认为innodb的锁都是行锁(尤其是select和insert操作的压根儿也不是一行),怎么可能发生死锁呢?

让我们模拟一下,分别在两个session中一行一行地交替执行两个事务,我们发现,确实在insert的时候死锁了

session 1:

 

session 2:

 

如果我们不着急去执行session 2中的insert的语句,而是查询一下存在哪些锁,发现如下:

什么是supremum pseudo-record?

supremum pseudo-record :相当于比索引中所有值都大,但却不存在索引中,相当于最后一行之后的间隙锁

解决办法:

 

参看: http://blog.itpub.net/26250550/viewspace-1070422/

 

问题: 两个select … for update ; 加的是共享锁?否则不能同时两个select语句都能成功执行。还如何查证?

不能简单地说 select … for update 加的是共享锁还是排他锁; 如果select有结果,则加行锁,此时为排他锁; 如果没有结果,则加间隙锁,此时为共享锁(和间隙大小没有关系); 如果没有在事务中,则select for update是不加锁的;

参看: Enabling InnoDB Monitors: https://dev.mysql.com/doc/refman/5.6/en/innodb-enabling-monitors.html

可以查看当前被设置的锁的信息:

部分信息如下:

 

下面是insert 语句等待时的锁情况:

 

学习资料:

http://hedengcheng.com/?p=771    非常不错

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据