Mysql如何保证数据不丢失

一、前置问题

  1. binlog, redolog区别

二、InnoDB实现原子级的持久性

1. 直接把buffer中的修改页写到磁盘的挑战

1)如何保证Mysql底层数据页的完整性

首先写磁盘操作的非原子性,事务提交后,直接把buffer中的修改页写入磁盘,如果此过程中数据库宕机,则可能导致事务写入不完整,且重启后无法恢复;

2)如何避免频繁写Mysql数据页导致性能下降

随机写盘的IO效率低和响应时间长。因为数据库数据按B+数的结构存储,其数据必然是不连续的;持久化操作必然是非顺序写,IO的操作必然导致客户端响应时间变大;

2. Innodb的解决方案——redo log

1)double write来避免partial page write,保证页完整性。

双写的原则是任何时候不破坏页的完整性。BufferPoll中的脏页会先把他保存到其他地方,保存成功后再去覆盖原有位置的页。这样无论何时都有一个完整的数据页。

2)通过AOF日志记录避免频繁刷盘

redo log是Innodb存储引擎引入的,用来解决事务级别的持久化和原子性;redo log的使用是建立在页完整的基础上的。

I、redo log存储了本次的事务的操作,其最后的行end trx_num来标识事务是否已完成;通过该行来原子性标识是否事务是否完成;

II、redo log顺序写的特性保证其IO效率高,响应快;

通过同步写redo log,异步刷新修改页到磁盘实现高响应;如果写磁盘发生宕机则通过重放redo log实现crash recovery,实现数据不丢失;

三、bin log

bin log是mysql server层的日志,主要用来实现主从同步;

四、redo log的二段式提交

innoDB为了使redo log和bin log保持同步,即保证主库和从库的同步,在收到事务的commit操作后,采用二段式提交实现;

1)第一步:pepare redo log,第一次提交

1
2
3
4
start tx_num;
write operate_1;
write operate_n;
pepare tx_num;

2)第二步:write bin log

1
write binlog;

3)第三步:end tx_num,第二次提交

1
end tx_num;

此时,有三种场景:

1)第一步失败(redo log中无prepare tx_num行)- mysql认为事务提交失败,忽略事务;

2)第二步失败(redo log中存在prepare tx_num行)- mysql通过redo log恢复bin log,继续执行第三步,事务提交成功;

3)第三步失败(redo log中存在prepare tx_num行)- 重启后继续执行第三步,事务提交成功;

参考

  1. https://www.cnblogs.com/biao/p/11820310.html
  2. https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html
  3. https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_checksum_algorithm
  4. https://blog.csdn.net/jolly10/article/details/79791574

评论