|
@@ -32,29 +32,9 @@ MySQL是一个服务器/客户端架构的软件,对于同一个服务器来
|
|
|
|
|
|
如图所示,当Session B中的事务更新了id为1的记录后,之后Session A中的事务再去访问这条记录时就被卡住了,直到Session B中的事务提交之后,Session A中的事务才可以获取到查询结果。
|
|
|
|
|
|
-### 版本链
|
|
|
-对于使用InnoDB存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列(row_id并不是必要的,我们创建的表中有主键或者非NULL唯一键时都不会包含row_id列):
|
|
|
+### 幻读
|
|
|
+假设现在有两个事务A、B:
|
|
|
|
|
|
-
|
|
|
-trx_id:每次对某条聚簇索引记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列。
|
|
|
-
|
|
|
-
|
|
|
-roll_pointer:每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。
|
|
|
-
|
|
|
-
|
|
|
-比方说我们的表t现在只包含一条记录:
|
|
|
-mysql> SELECT * FROM t;
|
|
|
-+----+--------+
|
|
|
-| id | c |
|
|
|
-+----+--------+
|
|
|
-| 1 | 刘备 |
|
|
|
-+----+--------+
|
|
|
-1 row in set (0.01 sec)
|
|
|
-复制代码假设插入该记录的事务id为80,那么此刻该条记录的示意图如下所示:
|
|
|
-
|
|
|
-假设之后两个id分别为100、200的事务对这条记录进行UPDATE操作,操作流程如下:
|
|
|
-
|
|
|
-小贴士:
|
|
|
-
|
|
|
-能不能在两个事务中交叉更新同一条记录呢?哈哈,这是不可以滴,第一个事务更新了某条记录后,就会给这条记录加锁,另一个事务再次更新时就需要等待第一个事务提交了,把锁释放之后才可以继续更新。本篇文章不是讨论锁的,有关锁的更多细节我们之后再说。
|
|
|
-每次对记录进行改动,都会记录一条undo日志,每条undo日志也都有一个roll_pointer属性(INSERT操作对应的undo日志没有该属性,因为该记录并没有更早的版本),可以将这些undo日志都连起来,串成一个链表,所以现在的情况就像下图一样:
|
|
|
+事务A先查询id大于2的账户记录,得到记录id=2和id=3的两条记录
|
|
|
+这时候,事务B开启,插入一条id=4的记录,并且提交了
|
|
|
+事务A再去执行相同的查询,却得到了id=2,3,4的3条记录了。
|