共计 1378 个字符,预计需要花费 4 分钟才能阅读完成。
undo 日志链表
这个要从 MySql – 对 update 是怎么解决的的 undo 日志文件说起。
咱们对数据进行批改之前,都会把数据写入到 undo 日志中,如果对一条数据做了屡次批改,那这些数据就会通过链表关联起来。
MySql – 一条语句是怎么插入磁盘的提到了一条数据的构造,咱们这里就用 DB_TRX_ID 事务 ID,DB_ROLL_PTR 事务回滚以及具体的数据 DATA 来简化一条数据,上面用简略的例子解说一下这个 undo 日志链表。
步骤一:
插入一条数据 DATA 为,AAA,此时的 DB_TRX_ID 为 1,DB_ROLL_PTR 为空,如下图:
步骤二:
批改这个数据 DATA 为 BBB,此时的 DB_TRX_ID 为 2,DB_ROLL_PTR 指向批改前的数据,如下图:
步骤三:
批改这个数据 DATA 为 CCC,此时的 DB_TRX_ID 为 3,DB_ROLL_PTR 指向批改前的数据,如下图:
ReadView 机制
MySql 是反对多线程的,所以当多个事务提交的时候,其中一个事务就会创立一个 ReadView。
ReadView 的构造如下:
- m_ids:以后未提交的事务
- creator_trx_id:创立 ReadView 的事务
- min_trx_id:m_ids 中最小的事务 id
max_trx_id:最大的事务 id+1
咱们同样用一个例子来阐明这个机制。
假如事务 1 插入了 DATA 为 AAA 后,事务 2 和事务 3 对这条数据进行了查问和批改。步骤 1:
事务 2 创立了 ReadView。所以 ReadView 如下:
- m_ids 为 2 和 3。
- creator_trx_id 为 2。
- min_trx_id 为 2。
max_trx_id 为 4。
步骤 2:
事务 2 查问了这条语句。
事务 2 首先会判断 min_trx_id(2)和这条数据的 DB_TRX_ID(1),此时 2 比 1 大,阐明 ReadView 里的事务都是在以后数据的事务后创立的。咱们当然能够读取之前的事务提交的数据。
此时事务 2 间接读取这条数据的 DATA,AAA。步骤 3:
事务 3 批改了这条语句,DATA 改为 BBB。
事务 3 也会判断 min_trx_id(2)和这条数据的 DB_TRX_ID(1),发现是之前事务提交 的数据,所以他就间接批改了此数据。步骤 4:
事务 2 持续查问了这条语句。
事务 2 发现 DB_TRX_ID(3)比 min_trx_id(2)大,然而比 max_trx_id(4)小,同时在 m_ids(2,3)中,所以晓得了这个批改数据的事务是跟本人在同一个 ReadView 中的,那他就不能读取以后事务的数据,就依据 DB_ROLL_PTR 读取上一个数据。
所以又读到了 DB_TRX_ID(1)的 DATA 的值 AAA。这就是可反复读。步骤 5:
事务 4 批改了这条语句,DATA 改为 CCC。
事务 4 会生成新的 ReadView,而后发现 DB_TRX_ID(3)是之前事务提交 的数据,所以他就间接批改了此数据。步骤 6:
事务 2 持续查问这条语句,他比照 DB_TRX_ID(4)和 max_trx_id(4),发现这个数据被比本人前面的事务提交了,所以他也不能看到这个事务提交的数据,于是他就顺着链表找到 DB_TRX_ID(3),判断同步骤 6,最终还是找到了 DB_TRX_ID(1)的 DATA 为 AAA 的数据。
以上例子能够看到,ReadView 机制能够保障能够读取到之前提交事务的数据,然而读取不到一起执行的事务以及之后的事务提交的数据。