发生在数据库内部的两阶段提交

    1. // 语句为
    2. update T set c = c + 1 where ID = 2

    6u78dk80qc.png
    在最后提交事务时有三个步骤:

    • 写入 redo log, 处于 prepare 状态
    • 写 binlog
    • 修改 redo log 状态为 commir

    因为 redo log 的 提交分为 prepare 和 commit 两个阶段,所以称为两阶段提交

    思考一下为何需要两阶段提交


    1. 假如 redo log 不分为 prepare 和 commit 怎么办,在写完 redo log 后 没有写 binlog 会发生的情况:

    (1) 先写 redo log 再写 bin log,此时 c = c + 1的这个数据页的变化已经写入其中,恢复数据时,c = c + 1,但是 binlog 中没写,即不包含此语句,此时进行恢复会发现与原数据库的值不同。
    (2)先写 binlog 再写 redo log, 此时 c = c + 1 的这个语句已经写入了其中,但是数据页的变更没有写入 redo log 中, redolog 中的 LNS 就会大于数据页中的 LNS,而此时并未提交 c = 0,但是 此时 bin log 中记录 c = c + 1, 恢复出来的时候就会发现完全不同。

    崩溃恢复


    包括一下两个情况,时刻 A 以及 时刻 B

    • 时刻A 时, 写入 redo log,此时处于 prepare 阶段,然后崩溃,此时没有写 binlog

    然后会出现一些问题:此事务处于 prepare 状态,但是没有写入 binlog 。在恢复时,此时此事务还未提交,此时根据 bin log ,恢复的数据为 c = c;

    • 时刻 B 时,写入了 bin log 但是未提交事务为 commit 状态,此时 bin log 中存在对应的事务,此时则提交事务,恢复数据为 c = c + 1 ;