共计 2473 个字符,预计需要花费 7 分钟才能阅读完成。
这篇文章主要介绍 MySQL 中 InnoDB 存储引擎架构的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
InnoDB 组件结构:
buffer pool : 缓冲池,缓存磁盘的数据
redo log buffer:记录对缓冲池的操作,根据策略写入磁盘防止宕机但事务已经提交而丢失数据
undo log:当对缓冲池的数据进行修改时,在事务未提交的时候都可以进行回滚,将旧值写入 undo 日志文件便于回滚,此时缓冲池的数据与磁盘中的不一致,是脏数据
1. Buffer Pool
假设现在有一条更新语句:
update users set name = lisi where id = 1
需要更新到数据库,InnoDB 会执行哪些操作呢?
首先,InnoDB 会判读缓冲池里是否存在 id = 1 这条数据,如果不存在则从磁盘中加载到缓冲池中,而且还会对这行数据加独占锁,防止多个 sql 同时修改这行数据。
2. undo 日志文件
假设 id = 1 这条数据 name 原来的值 name = zhangsan,现在我们要更新为 name = lisi , 那么我们就需要把旧值 name= zhangsan 和 id= 1 这些信息写入到 undo 日志文件中。
对于熟悉数据库的同学来说都了解事务的概念,在事务未提交之前,所有操作都有可能进行回滚,即可以把 name = lisi 回滚到 name = zhangsan,所以将更新前的值写到 undo 日志文件。
3. 更新 buffer pool 数据
在 undo 日志文件写入完毕之后,便开始更新内存中的这条数据。把 id = 1 的 name = zhangsan 更新为 name = lisi。这时内存中的数据已经更新完毕,但磁盘上的还没有变化,此时出现了不一致的脏数据。
这时可能有一个疑问,万一事务提交完成,但 MySQL 服务宕机了,而内存中的数据还没写入到磁盘,是不是会造成数据丢失而造成 sql 执行数据前后不一致?
4. redo log buffer
在 InnoDB 结构中,有一个 redo log buffer 缓冲区存放 redo 日志,所谓 redo 日志,例如 把 id=1,name= zhangsan 修改为 name= lisi 便是一条日志。
但这时 redo log buffer 还仅仅存在内存中,没能实现 MySQL 宕机后的数据恢复。
5. 事务没提交,数据库宕机后有影响吗?
其实并没有影响,事务没有提交,意味着执行没有成功,就算 MySQL 崩溃或者宕机后,内存中的 buffer pool 和 redo log buffer 修改过的数据都会丢失,也并不影响数据前后的一致性。如果事务提交失败,那数据库的数据更加不会改变。
6. 提交事务,redo 日志的配置策略
在提交事务时,redo 日记会根据策略实现把 redo 日志从 redo log buffer 里写入磁盘。策略通过 innoDB_flush_log_at_trx_commit 来配置。
innoDB_flush_log_at_trx_commit 的参数为 0,就算事务提交后,也不会把 redo 日志写入磁盘。MySQL 宕机后会内存中的数据会丢失。
innoDB_flush_log_at_trx_commit 的参数为 1,事务提交后,redo 日志会从内存刷入磁盘,只要事务提交成功,redo log 就必然存在磁盘里。
此时就算 buffer pool 的数据没有刷进磁盘,也可以从 redo log 中得知修改过哪些数据,MySQL 宕机重启后,可以从 redo 日志中恢复修改的数据。
innoDB_flush_log_at_trx_commit 的参数为 2,事务提交后,redo log 仅仅停留在 os cache 中,还没刷进磁盘,万一此时服务宕机了。那么 os cache 中的数据也会丢失,即使事务提交成功,也会造成数据丢失。
看完这几种相信为了保证数据安全,参数为 1 是最佳策略。
7. 事务的最终提交,binlog
binlog 其实是属于 MySQL Server 的日志文件,而在这出提出是因为与 redo log 有着很大的关联。
1) biglog 与 redo log 的区别
redo log: 记录的是偏物理性质重做日志,比如“对哪个数据页中的什么记录,做了哪些修改”
binlog:偏向于逻辑性的日志,如:“对 users 表中的 id=10 的一行数据做了更新操作,更新以后的值是什么”
2) 提交事务的时候同时写入 binlog
在执行更新的同时,innoDB 与执行器一直在交互,包括加载数据到缓冲池,写入 undo 日志文件,更新内存数据,写 redo 日志和刷入磁盘等。而对 binlog 的写入也是由执行器执行。
其中 1、2、3、4 步骤为执行更新语句做的事,而 5、6 是提交事务开始做的事。
3) binlog 日志刷盘策略分析
sync_binlog 参数控制 binlog 的刷盘策略
sync_ binlog 默认值是 0,提交事务后,会把 binlog 日志存在 os cache 中,MySQL 宕机后会造成 os cache 中数据的丢失
sync_binlog 值为 1,提交事务后,把 binlog 日志直接刷入磁盘中。
4) 基于 binlog 和 redo log 完成事务的提交
binlog 写入磁盘后,会把 binlog 日志文件所在的位置和文件名称都写入 redo log 日志文件中,同时在 redo log 日志文件里写入一个 commit 标记。
5) commit 标记有什么意义?
commit 标记意义着保持 redo log 和 binlog 日志一致。如果在步骤 5 或者步骤 6,事务提交开始,MySQL 宕机了,redo log 中并没有 commit 标记,都算事务提交失败。
意味着 commint 标记是事务最终提交成功。
8. buffer pool 脏数据刷入磁盘
脏数据刷入磁盘是由后台 IO 线程随机刷入磁盘的。
这时候考虑到,在刷入磁盘之前,MySQL 宕机怎么办?这时候,事务已经提交成功,redo log 中也有 commit 标记,就算宕机了,重启后,也会根据 redo 日志文件把数据更新到内存中,等待 IO 线程的刷盘。
以上是“MySQL 中 InnoDB 存储引擎架构的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注丸趣 TV 行业资讯频道!