关于java:S-锁与-X-锁当前读与快照读

5次阅读

共计 1319 个字符,预计需要花费 4 分钟才能阅读完成。

MySQL 中的锁还是蛮多的,在之前的文章中,松哥和大家介绍过 MySQL 中的 MDL 锁(为什么执行 alter 更新表要谨慎?),明天咱们再来看看 MySQL 中比拟重要的两个锁:S 锁和 X 锁。

1. S 锁

S 锁,英文为 Shared Lock,中文译作共享锁,有时候咱们也称之为读锁,即 Read Lock。S 锁之间是共享的,或者说是互不阻塞的。

当事务读取一条记录时,须要先获取该记录的 S 锁。

举个例子:

事务 T1 对记录 R1 加上了 S 锁,那么事务 T1 能够读取 R1 这一行记录,然而不能批改 R1,其余事务 T2 能够持续对 R1 增加 S 锁,然而不能增加 X 锁,只有当 R1 下面的 S 锁开释了,能力加上 X 锁。

举一个加 S 锁的例子,如下图:

此时,对于 id=1 的这条记录,只能读取不能批改了。假如在另外一个事务 T 中,执行如下 SQL 是没问题的,因为 S 锁是共享锁,S 锁和 S 锁之间是兼容的:

select * from user where id=1 lock in share mode;

然而如果执行如下 SQL 则会被阻塞,因为批改数据须要获取 X 锁,而 S 锁和 X 锁不兼容:

update user set username='javaboy' where id=1;

下面这个更新语句外部会获取 X 锁,对于一些手动增加了 X 锁的查问语句,也会阻塞,例如上面这个:

能够看到,这个 SQL 执行之后就被阻塞了。

2. X 锁

X 锁,英文为 Exclusive Lock,中文译作排他锁,有时候咱们也称之为写锁,即 Write Lock。如同它的名字,X 锁是具备排他性的,即一个写锁会阻塞其余的 X 锁和 S 锁。

当事务须要批改一条记录时,须要先获取该记录的 X 锁。

举个例子:

事务 T1 对记录 R1 加上了 X 锁,那么事务 T1 即能够读取 R1 也能够批改 R1,而其余事务则不能对 R1 再增加任何锁,直到 T1 开释了 R1 上的锁。

如上文图示,锁定读的格局是这样的:

select .... for update;

3. 以后读与快照读

由下面这两种锁,又引申进去两种读:

3.1 快照读

快照读(SnapShot Read)是一种一致性不加锁的读,是 InnoDB 存储引擎并发如此之高的外围起因之一。

在可反复读的隔离级别下,事务启动的时候,就会针对以后库拍一个照片(快照),快照读读取到的数据要么就是拍照时的数据,即事务开启那一瞬间数据库中的数据,要么就是以后事务本身插入 / 批改过的数据。

咱们日常所用的不加锁的查问,都属于快照读,这个我就不演示了。

3.2 以后读

与快照读绝对应的就是以后读,以后读就是读取最新数据,而不是历史版本的数据,换言之,在可反复读隔离级别下,如果应用了以后读,也能够读到别的事务已提交的数据。

松哥举个例子:

MySQL 事务开启两个会话 A 和 B。

首先在 A 会话中开启事务并查问 id 为 1 的记录:

接下来咱们在 B 会话中对 id 为 1 的数据进行批改,如下:

留神 B 会话不要开启事务或者开启了及时提交事务,否则 update 语句占用一把排他锁会导致一会在 A 会话中用锁时产生阻塞。

接下来,回到 A 会话中持续做查问操作,如下:

能够看到,A 会话中第一个查问是快照读,读取到的是以后事务开启时的数据状态,前面两个查问则是以后读,读取到了以后最新的数据(B 会话中批改后的数据)。

4. 小结

好啦,一个小小的知识点,与日俱增,fighting!

正文完
 0