更新时间:2021-01-22 17:47:12 来源:极悦 浏览969次
所谓MySQL事务持久性就是事务一旦提交,就是永久性的,不会因为宕机等故障导致数据丢失(外力影响不保证,比如磁盘损害)。持久性是保证了MySQL数据库的高可靠性(High Reliability),而不是高可用性(Hign Availability)。
MySQL的innoDB存储引擎,使用Redo log保证了事务的持久性。当事务提交时,必须先将事务的所有日志写入日志文件进行持久化,就是我们常说的WAL(write ahead log)机制。这样才能保证断电或宕机等情况发生后,已提交的事务不会丢失,这个能力称为 crash-safe。
Redo log包括两部分,重做日志缓冲(redo log buffer)和重做日志文件(redo log file),前者是易失的缓存,后者是持久化的文件。
举一个事务的例子:
步骤1:begin;
步骤2:insert into t1 …r
步骤3:insert into t2 …
步骤4:commit;
这个事务的写入过程实际拆解如下:
重点关注在这个事务提交前,将redo log的写入拆成了两个步骤,prepare 和 commit,这就是"两阶段提交”。那么为什么要采用两阶段提交呢?
实际上,两阶段提交是分布式系统常用的机制。MySQL使用了两阶段提交后,也是为了保证事务的持久性。Redo log 和bingo 有一个共同的数据字段,叫 XID,崩溃恢复的时候,会按顺序扫描 redo log。
假设在写入binlog前系统崩溃,那么数据库恢复后顺序扫描 redo log,碰到只有 parepare、而没有 commit 的 redo log,就拿着 XID 去 binlog 找对应的事务,而且binlog也没写入,所以事务就直接回滚了。
假设在写入binlog之后,事务提交前数据库崩溃,那么数据库恢复后顺序扫描 redo log,碰到既有 prepare、又有 commit 的 redo log,就直接提交,保证数据不丢失。
这个事务要往两个表中插入记录,插入数据的过程中,生成的日志都得先写入redo log buffer ,等到commit的时候,才真正把日志写到 redo log 文件。(当然,这里不绝对,因为redo log buffer可能因为其他原因被迫刷新到redo log)。
而为了确保每次日志都能写入日志文件,在每次将重做日志缓冲写入重做日志文件后,InnoDB存储引擎都需要调用一次fsync操作,确保写入了磁盘。
对于redo log的持久化,可以如下图所示。
1)先写入redo log buffer,在蓝色区域。
2)写入redo log file,但是还没有fsync,这时候是处于黄色的位置,处于系统缓存。
3)调用fsync,真正写入磁盘。
为了控制 redo log 的写入策略,InnoDB 提供了 innodb_flush_log_at_trx_commit 参数,它有三种可能取值:
设置为 0 的时候,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中 ;
设置为 1 的时候,表示每次事务提交时都将 redo log 直接持久化到磁盘;
设置为 2 的时候,表示每次事务提交时都只是把 redo log 写到 page cache。
binlog的写入和redo log一样,也是包括bingo cache和bingo file,同样跟上面的三色层次类似(当然,binlog是server层的,不是存储引擎层的),包括log buffer、文件系统page cache、hard disk。
写入page cache 和 fsync到disk 的时机,是由参数 sync_binlog 控制的:
sync_binlog=0 的时候,表示每次提交事务都只 写入文件系统的page cache,不 fsync;
sync_binlog=1 的时候,表示每次提交事务都会执行 fsync;
sync_binlog=N(N>1) 的时候,表示每次提交事务都写入文件系统的page cache,但累积 N 个事务后才 fsync。(如果主机发生异常重启,会丢失最近 N 个事务的 binlog 日志)
通常我们说MySQL的“双 1”配置,指的就是sync_binlog和 innodb_flush_log_at_trx_commit 都设置成 1。也就是说,一个事务完整提交前,需要等待两次刷盘,一次是 redo log(prepare 阶段),一次是 binlog。
以上就是MySQL的innoDB存储引擎,使用Redo log实现了MySQL事务持久性。除此之外,MySQL事务的其他特性也有着各自各样的机制来实现,详情可以观看本站的MySQL教程,展开拓展性的学习。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习