当前位置: 首页 > 后端技术 > Java

不再有简单的意向锁

时间:2023-04-01 18:23:35 Java

InnoDB存储引擎支持多粒度锁,即允许行锁和表锁共存。当允许行锁和表锁共存时,可能会出现如下问题:比如我执行如下SQL:这条SQL执行完成后,给id为1的记录加了排它锁。此时这时,在另一个session中,如果我想给这个表加一个表级的共享锁,如下:locktableuserread;这时候就会出现一个问题,共享锁和排它锁是互斥的,要给表加共享锁,就得检查表中的每条记录是不是有排它锁。如果表的数据量比较大,运行效率会比较低。为了解决这个问题,今天介绍了我们的意向锁。为了使多级锁实用,InnoDB使用了意向锁。注意,意向锁是一种表级锁,它表示事务稍后对表中的行需要哪种类型的锁(共享或独占)。意向锁也分为两类:意向共享锁:意向共享锁(IS)表示事务打算对表中的个别行设置共享锁。意向排他锁:意向排他锁(IX)表示事务打算对表中的个别行设置排他锁。例如,对于SELECT...LOCKINSHAREMODE;IS锁会自动设置,对于SELECT...FORUPDATE会自动设置IX锁,IS锁和IX锁不需要手动设置,这是系统自动设置的。意向锁的加锁规则如下:事务在获取表中某行的共享锁之前,必须先获取该表的IS锁或强锁。在事务可以获取表中行的排他锁之前,它必须首先获取表上的IX锁。简而言之:IS和IX是表锁。它们存在的意义在于,以后你给一张表加一个表级的S锁或者X锁的时候,可以通过IS或者IX快速判断当前表是否有锁记录。就这样。所以IS和IX其实是兼容的,IX也是兼容的,如下表所示:而不兼容上表也很好理解:如果表上有IS,说明表中的记录有共享锁。这时候不能给表加排他锁(X锁),但是可以给表加共享锁(S锁)。如果表上有IX,说明表中的记录有排它锁。这时候不能给表加排他锁(X锁),也不能给表加共享锁(S锁)。一般来说,兼容关系是这样的:好的。首先,我们将系统变量innodb_status_output_locks设置为ON,如下:接下来,我们执行如下SQL锁定一行数据。这时会自动给表加一个IX锁:接下来我们在一个新的session中执行如下命令查看InnoDB存储引擎的情况:showengineinnodbstatus\G输出了很多信息,我们重点在TRANSACTIONS上,如下:可以看到:TABLELOCKtabletest08.usertrxid3564804lockmodeIX:这句话的意思是事务id为3564804的事务,为user表添加了intentexclusivelock(IX)。RECORDLOCKSspaceid851pageno3nbits80indexPRIMARYoftabletest08.usertrxid3564804lock_modeXlocksrecbutnotgap:这是一个锁结构的记录,这里的索引是PRIMARY,加的锁也是positive经典的记录锁(不是gap),因为索引是PRIMARY,所以这里没有gap锁,关于gap锁,下篇继续。好了,希望今天的文章能够让大家对意向锁有一个简单的认识。参考资料:https://dev.mysql.com/doc/ref...