数据库 - SQL更新一条语句的过程

402 阅读3分钟

这是我参与8月更文挑战的第30天,活动详情查看:8月更文挑战

SQL更新语句

SQL 的整个更新流程与查询语句的流程基本相同。只是在执行器阶段添加了redo log[重做日志]和binlog[归档日志]两部分内容

redo log

InnoDB引擎特有,用来保证crash_safe能力。运用到了WAL【write-Ahead Logging】技术,即先写日志再写磁盘

redo log和binlog的异同如下:

redo logbinlog
InnoDB引擎特有Server层,每个存储引擎都可以使用
物理日志 - 该数据页执行的操作是什么逻辑日志 - 语句的原始逻辑
循环写,空间固定用完追加写,数据不会被覆盖

具体流程

graph TD
A[命令要取出的行] --> B{该数据页是否在内存中};
B -->|No| C[从磁盘中读取到内存] --> D[返回行数据]; 
B ---->|Yes| D;
D --> E[对行数据进行计算];
E --> F[调用引擎返回新行];
F --> G[新行更新到内存];
G --> H[新行存入redo log, 状态变为prepare];
H --> I[写入binlog];
I --> J[提交事务, redo log变为commit状态];

两阶段提交

之所以使用两阶段提交,是为了保证两份日志的逻辑一致性,避免MySQL异常重启时导致的数据不一致。

若不是两阶段提交

  1. redo log写完,binlog 写时发生异常重启。此时redo log中已经包含了更新后的状态,而bin log中 仍是原值。由于redo log的crash_safe能力,数据能够恢复回来。但一旦用binlog来恢复临时库,则会发现与原库的值不同。
  2. binlog写完,redo log写时发生异常重启。此时bin log中是原值,崩溃恢复后仍是原值。但binlog中是新值,之后用binlog恢复就会多一个事务出来,与原库值不同。

若是两阶段提交

redo log写完,binlog写时异常重启。此时redo log是prepare状态,binlog中又失败,因此事务本身会回滚到原值。binlog恢复出一个库也是原值,则逻辑一致

redo_log - innodb_flush_log_at_trx_commit 参数设置成1 - 表示事务的redo log都直接持久化到磁盘

binlog - sync_binlog参数设置成1 - 表示每次事务的binlog都持久化到磁盘。

SQL更新语句

SQL 的整个更新流程与查询语句的流程基本相同。只是在执行器阶段添加了redo log[重做日志]和binlog[归档日志]两部分内容

redo log

InnoDB引擎特有,用来保证crash_safe能力。运用到了WAL【write-Ahead Logging】技术,即先写日志再写磁盘

redo log和binlog的异同如下:

redo logbinlog
InnoDB引擎特有Server层,每个存储引擎都可以使用
物理日志 - 该数据页执行的操作是什么逻辑日志 - 语句的原始逻辑
循环写,空间固定用完追加写,数据不会被覆盖

具体流程

graph TD
A[命令要取出的行] --> B{该数据页是否在内存中};
B -->|No| C[从磁盘中读取到内存] --> D[返回行数据]; 
B ---->|Yes| D;
D --> E[对行数据进行计算];
E --> F[调用引擎返回新行];
F --> G[新行更新到内存];
G --> H[新行存入redo log, 状态变为prepare];
H --> I[写入binlog];
I --> J[提交事务, redo log变为commit状态];

两阶段提交

之所以使用两阶段提交,是为了保证两份日志的逻辑一致性,避免MySQL异常重启时导致的数据不一致。

若不是两阶段提交

  1. redo log写完,binlog 写时发生异常重启。此时redo log中已经包含了更新后的状态,而bin log中 仍是原值。由于redo log的crash_safe能力,数据能够恢复回来。但一旦用binlog来恢复临时库,则会发现与原库的值不同。
  2. binlog写完,redo log写时发生异常重启。此时bin log中是原值,崩溃恢复后仍是原值。但binlog中是新值,之后用binlog恢复就会多一个事务出来,与原库值不同。

若是两阶段提交

redo log写完,binlog写时异常重启。此时redo log是prepare状态,binlog中又失败,因此事务本身会回滚到原值。binlog恢复出一个库也是原值,则逻辑一致

redo_log - innodb_flush_log_at_trx_commit 参数设置成1 - 表示事务的redo log都直接持久化到磁盘

binlog - sync_binlog参数设置成1 - 表示每次事务的binlog都持久化到磁盘。