定点分析: MySQL InnoDB是如何保证系统异常断电情况下的数据可靠性?

时间:2021-09-20 11:35:09

MySQL支持事务,所以保证数据可靠的前提是对数据的修改事务已经成功提交

这个问题可以解释为‘MySQL InnoDB是如何保证事务C(一致性)D(持久性)性的?’

可能出现的两种情况:

  1. (一致性)数据不一致。 例如本来在一个事务里要执行两条SQL,结果系统断电导致只有一条SQL执行成功了
  2. (持久性)写入数据丢失。 本来要写入的两条数据由于系统断电数据都没有写进去

MySQL遵循日志先行的准则,写日志要先于写数据。这里的日志包括redo日志和undo日志。redo日志用于记录数据更新后的的值,undo日志记录数据修改前的值,在写数据之前redo日志和undo日志都会

写到日志文件里。系统断电丢数据的主要原因是数据库为了提高性能会在IO上加缓存,比如insert一条数据可能不会立即刷入磁盘里,而是暂时写到系统的内存缓存里,当达到某个定义的阈值时才会把缓存

里的数据刷新到磁盘上,数据库里的数据和日志可以看成一行一行的数据,每一条数据或日志都有一个序列号,每次执行刷新缓存的时候都会把当前最新刷新到的序列号记录下来,比如当前数据刷新到了1000行,

redo日志执行到了3000行这样。这个在MySQL里叫做checkpoint(检查点),小于最新检查点的数据就表示已经持久化到磁盘里了,系统重启的时候只需要处理大于检查点的日志即可。

redo日志和undo日志的执行的简化流程如下:

假设有两个数据A,B值分别为1,2

A. 事务开始

B. 记录 A = 1 到undo log

C. 修改 A = 3

D. 记录 A = 3到redo log

E. 记录B = 2到undo log

F. 修改 B = 4

G. 记录B=4到redo log

H. 将redo log和undo log写入磁盘

I. 事务提交

当数据库系统重启时会把大于检查点的所有redo log表示的数据更新都重新执行一遍,包括未提交的事务。然后再

根据undo log把所有未提交的事务反向重做一遍(比如原始sql为insert,那么就执行delete,redo log和

undo log都是存储引擎层面的,所以这里的所有执行动作都是基于数据文件的)。

通过执行redo日志可以保证只要成功提交了事务,那么提交的数据就不会丢失。

通过执行undo日志可以保证没有提交成功的日志,不会造成写一半数据的情况。

参考:

https://www.letiantian.me/2014-06-18-db-undo-redo-checkpoint/

http://www.zhdba.com/mysqlops/2012/04/06/innodb-log1/

https://www.cnblogs.com/chenpingzhao/p/5107480.html/

https://www.cnblogs.com/fjdingsd/p/5273008.html/