【MySQL(八)】一致性非锁定读 锁定读

mysql的锁有若干种分类标准,这里看下行锁中的读锁与写锁。

读锁即S锁,也叫共享锁,当事务读取一行数据时,会尝试在记录上加S锁;

写锁即X锁,也叫排它锁,当事务要更新或者删除一行数据时,会尝试在记录上加X锁;

只有S锁和S锁是互相兼容的,其余情况都是不兼容的,需要等待。

【MySQL(八)】一致性非锁定读 锁定读默认情况下,所得兼容性如上面的表格所示。

下面我们专门看下读取操作是如何上锁的,或者说是否完全如上表所示。

在serializable级别下,会完全按照如上规则运行。在其他级别下,读取可以发生在上了X锁的数据上,除非读取使用了for update语法。关于serializable隔离级别,参见https://blog.csdn.net/u010900754/article/details/78108735

举个例子:

T1:

【MySQL(八)】一致性非锁定读 锁定读

T1先更新一条数据,上了X锁;

T2:

【MySQL(八)】一致性非锁定读 锁定读

T2读取数据时发生了锁等待;

结论:在serializable隔离级别下,S锁和X锁按照锁兼容性执行;这样的读取叫做锁定读,锁定读的含义是事务读取有X锁的数据时,必须等待。除了在serializable级别下会有锁定读,在其他级别下,使用select for update查询时也可以锁定读,也可以理解为读取时必须先上X锁;

for update例子:

T1:

【MySQL(八)】一致性非锁定读 锁定读

T1先更新一条数据,上了X锁;

T2:

【MySQL(八)】一致性非锁定读 锁定读

T2读取数据,如果不写for update,那么由于是在repeatable read隔离级别下,使用的是非锁定读,是可以读的(见下面的例子);但是由于加了for update,就需要先上X锁,那么会锁等待。

但是在其他隔离级别下呢?

如果一个事务在一行记录上加了X锁,其余事务仍然可以在这一行数据上加S锁,进行读取,读到什么内容取决于隔离级别设置,这个不在本篇展开。为什么要这么做?因为如果完全按照锁兼容性来执行,那么大量事务并发时,会有很多锁等待,降低了事务的并发性。事实上,innodb引擎使用了一种叫做MVCC的机制,来实现上述机制。也就是即使别的事务在该行数据上加了X锁,当前事务仍然能够读取数据,MVCC机制用于保证该隔离级别下的数据一致性。

例子:

T1:

【MySQL(八)】一致性非锁定读 锁定读

T1先更新一条数据,上了X锁;

T2:

【MySQL(八)】一致性非锁定读 锁定读

T2仍然可以读取到数据。

结论:非锁定读可以让事务读取到已经上了X锁的数据,原理是MVCC机制。

总结:

1.明白锁定读与非锁定读的概念;

2.锁定读与非锁定读的区别在于事务如果读取已经被上了X锁的数据;