麦当劳怎么想的?他们甚至用外卖垃圾来拍摄广告
06-21
前言上一篇文章《InnoDB在SQL查询中的关键功能和优化策略》讲解了InnoDB的查询操作和优化事项。然而,由于MySQL是一个数据存储产品,如何保证数据的持久性和不丢失是最重要的。
如果您有兴趣,可以关注这篇文章来了解一下。 Buffer Pool与DML的关系。
InnoDB中的“Buffer Pool”不仅在查询时起到提高效率的作用,而且为了减少插入、更新、删除等DML操作时与磁盘的频繁交互,这些更新也会被放在第一位。对Buffer Pool中缓存的数据页进行操作,然后将这些更新的“脏页”刷新到磁盘。
这次涉及到一个问题:如果MySQL服务宕机了,内存中更新的数据会丢失吗?答案是肯定会有丢失,但是MySQL尽力防止数据丢失。接下来我们看看MySQL是怎么做的。
这里把结构图贴出来,方便后面介绍的时候理解。这里插入图片来描述DML操作过程。
加载数据页。从上面可以看出,行记录位于数据页中。
因此,当InnoDB接收到DML操作请求时,它仍然会寻找“数据页”,并且搜索过程会跟上。文档查询行记录的过程是一样的。
这里先说一下,插入请求会根据主键索引找到数据页,更新和删除会根据查询条件找到数据页。简而言之,必须先将“数据页”加载到“Buffer Pool”中,然后才能执行下一步。
update记录定位到数据页后,insert操作是向数据页添加一行记录,delete是标记该行记录的‘删除标记’,update是先删除再添加。这是因为存在可变长度字段类型。
,例如 varchar。每次更新时,该类数据占用的内存不固定,所以先删除,再添加。
这里的删除标记是行记录的字段,即除了业务字段数据之外,InnoDB默认为每行记录添加字段,所以一条行记录大致如下图,也就是“行”格式”前面提到过。在此插入图片说明。
找到数据页并更新记录后,DML操作完成,但还没有落地到磁盘上。这时候直接刷盘还不能算是完成了吗?数据持久化方案是可以的,但是如果每次DML操作都需要flush一个16KB的数据页到磁盘,效率极低,估计没人会用MySQL。
但是,如果数据没有刷新到磁盘,MySQL服务就会宕机,数据就会丢失。MySQL 这里的解决方案是等待合适的时间将批量的“脏页”异步刷新到磁盘。
首先,将更新的记录以日志的形式快速刷新到磁盘。我们先看第一点,什么时候合适?在适当的时间冲洗磁盘。
当“Buffer Pool”中的“脏页”达到一定阈值时,InnoDB会将这些脏页刷新到磁盘。这个阈值可以通过innodb_max_dirty_pages_pct参数查看或设置。
相关命令如下: 代码语言:sql copy -- 查看脏页刷新阈值 show Variables like 'innodb_max_dirty_pages_pct' -- 在线设置脏页刷新阈值。当脏页在Buffer Pool中占据70时刷新SET GLOBAL innodb_max_dirty_pages_pct = 70%。
在此插入图片说明。当然,这个适当的时间只是为了减少与磁盘的交互,提高性能。
它不能保证数据不会丢失。使用双写机制刷新“脏页”时还有一个非常重要的注意事项:因为InnoDB的页面大小为16KB,而一般操作系统的页面大小为4KB。
这意味着当InnoDB将这些“脏页”刷新到磁盘时,它会在操作系统层面被分为4个4KB页。在这种情况下,如果由于MySQL宕机或者其他异常,其中某一页没有成功刷新到磁盘,就会出现“页面损坏”,导致数据不完整。
在此插入图片说明。因此,这里InnoDB采用的双写机制,会将这些“脏页”先写入到结构图中的“Doublewrite Buffer”中,然后再刷新到磁盘,然后再刷新到对应的表空间。
,当发生故障时,可以通过双写缓冲区进行恢复。 “Doublewrite Buffer”会不会造成“页面损坏”? “Doublewrite Buffer”的大小是独立且固定的,不根据页面大小进行划分。
因此,它不受操作系统中页面大小的限制,并且不会发生“页面损坏”。另外,先使用顺序IO将数据页写入“Doublewrite Buffer”,然后使用随机IO异步刷新到表空间也可以提高写入性能。
这里插入图片描述,看第二点。为什么要先以日志的形式刷新到磁盘呢? log-first机制更新“Buffer Pool”中的数据页后,由于这些“脏页”不会及时刷新到磁盘,为了避免数据丢失,会写入本次DML操作的副本“日志缓冲区”并将其刷新到磁盘。
与16KB数据页相比,数据量会小很多。而且写入日志文件时是append操作,是顺序IO,效率很高。
如下图所示,哪种写法效率更高,一目了然。在此插入图片说明。
这里所说的日志文件就是经常听到的“Redo Log”。即使MySQL宕机了,通过磁盘上的redolog,也可以将数据尽可能恢复到MySQL启动时宕机前的样子。
当然,还有“撤消日志”。由于与本文的重点没有直接影响,所以不再赘述。
这种日志优先(WAL)机制也是MySQL用来提高效率和保证数据可靠性的一种方式。为什么要尽可能恢复?日志刷新机制因为“Log Buffer”中的日志数据何时刷新到磁盘是由innodb_flush_log_at_trx_commit和innodb_flush_log_at_timeout这两个参数决定的。
innodb_flush_log_at_trx_commit 默认为1,表示每次事务提交后都会刷新到磁盘。当innodb_flush_log_at_trx_commit设置为0时,不会根据事务提交进行刷新,而是根据innodb_flush_log_at_timeout设置的时间定时刷新,默认为1秒。
当innodb_flush_log_at_trx_commit设置为2时,日志仅写入操作系统中的缓存,然后根据innodb_flush_log_at_timeout定期刷新。注意:如果事务在innodb_flush_log_at_timeout内没有发生,也会被刷新到磁盘。
如果MySQL服务宕机时,“Log Buffer”中的日志没有刷新到磁盘,这部分数据也会丢失,重启后也无法恢复。所以如果不想丢失数据,在性能可以接受的情况下,尽量将innodb_flush_log_at_trx_commit设置为1。
“重做日志”如何恢复数据?重做日志恢复数据。首先,重做日志会记录DML操作类型、数据表空间、数据页以及具体修改内容。
以insert into t1(1,'hi')为例,对应的重做日志内容大致如下 此处插入图片说明。如果innodb_flush_log_at_trx_commit的值为1,那么当DML操作事务提交时,重做日志将被刷新到磁盘。
成功刷新到磁盘后,就可以认为数据已经成功写入。此时,如果“脏页”在刷新到磁盘之前就崩溃了,那么MySQL下次启动时就会加载重做日志。
如果重做日志中包含数据,则表示需要恢复该数据。这时就可以通过重做日志的内容来重构“脏页”,将其恢复到宕机前的状态。
如何构建“脏页”?事实上,每次写入重做日志时都会记录一个“LSN(日志序列号)”,这个值记录了“数据页”中最后修改的日志序列位置。 MySQL在启动时通过LSN比较重做日志和数据页。
如果数据页中的LSN小于重做日志的LSN,则数据页将被加载到“Buffer Pool”中,然后根据重做日志的内容构造“脏页”。 ”,等待下一次刷新到磁盘,数据就会恢复。
此处插入图片描述,如下所示。注意:此恢复过程侧重于重做。
其实还涉及到“Change Buffer”、“Undo Log”等操作。这里不做解释。
“Doublewrite Buffer”和“redo log”都是恢复数据,不是冲突吗?不存在冲突。 “Doublewrite Buffer”恢复“页面损坏”的整个数据页,而Redo Log只能恢复某个DML操作。
综上所述,InnoDB通过以上操作可以尽可能保证MySQL不丢失数据。最后我们总结一下MySQL是如何保证数据不丢失的:为了避免频繁与磁盘交互,每个DML操作都会先将页面缓存在“缓冲池”中,执行过程中缓存页面就变成了“脏页面”更新后,然后根据参数innodb_max_dirty_pages_pct将“脏页”刷新到磁盘。
由于在“脏页”刷新到磁盘之前可能会出现MySQL宕机等异常行为,导致数据丢失,因此MySQL使用log-ahead(WAL)机制将DML操作以日志的形式记录到“重做日志”中,然后根据innodb_flush_log_at_trx_commit和innodb_flush_log_at_timeout这两个参数将“Redo Log”Flush到磁盘进行恢复。在刷新“脏页”到磁盘时,为了避免“页损坏”,InnoDB采用双写机制,首先将这些脏页依次写入“Doublewrite Buffer”,然后异步刷新数据页到各个表空间。
,这种方法不仅可以提高写入效率,还可以保证数据的完整性。如果MySQL在“脏页”刷新到磁盘之前崩溃了,则下次启动时将通过重做日志构造脏页以实现数据恢复。
通过以上步骤,MySQL尽可能不丢失数据。我正在参加第五期腾讯科技创造特训营有奖征文比赛。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-21
06-17
06-17
06-08
06-06
06-17
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用