master节点会将所有的写操作记录到binlog中,slave节点会有专门的I/O线程读取master节点的binlog,将写操作同步到当前所在的slave节点 。

文章插图
6.2.2 数据恢复假如你在阅读这篇文章的时候觉得我写得实在太好,拍案叫绝的时候一不小心把公司的数据库给删了,你该怎么做才能恢复到你删库之前的那个时刻的状态?
这个时候就要用到binlog了,前提是binlog没有被删除,否则,神仙也救不了你了 。
通常情况下,公司会定期对数据库进行全量备份,可能隔一个月,一周,甚至可能每天都备份一次 。运气好的话你可以使用前一天的全量备份,恢复到前一天的某时刻状态(或者一周、一月之前),然后从全量备份的时刻开始,从binlog中提取该时刻之后(前提是你的binlog里面存放了这段时间的日志)的所有写操作(当然,你得过滤掉你的删库操作),然后进行操作回放就可以了 。
是不是很简单?
问题又来了 。再看一眼我们的更新语句 。
update t_user_innodb set name ='chanmufeng1994' where id = 1;
假如这条更新语句已经被写入到了redo日志,还没来得及写binlog的时候,MySQL宕机重启了,我们看一下会发生什么 。
因为redo日志可以在重启的时候用于恢复数据,所以写入磁盘的是chanmufeng1994 。但是binlog里面没有记录这个逻辑日志,所以这时候用binlog去恢复数据或者同步到从库,就会出现数据不一致的情况 。
所以在写两个日志的情况下,就类似于「分布式事务」的情况,如果你不清楚分布式事务是个什么东西也没关系,我在之后的文章会介绍到 。能够明确的就是redo日志和binlog日志如果单纯依次进行提交是无法保证两种日志都写成功或者都写失败的 。
我们需要「两阶段提交」 。
6.3 两阶段提交
两阶段提交不是MySQL的专利,两阶段提交是一种跨系统维持数据逻辑一致性的常见方案,尤其在分布式事务上,所以请读者重点体会思想我们把redo日志的提交分成两步,两步中redo日志的状态分别是prepare和commit 。步骤如下
- InnoDB存储引擎将更改更新到内存中后,同时将这个更新操作记录到redo日志里面,此时redo日志处于prepare状态;
- 执行器生成这个操作的binlog,并将binlog刷盘;
- 执行器调用InnoDB的提交事务接口,InnoDB把刚刚写入的redo日志改成commit状态 。至此,所有操作完成 。

文章插图
加上两阶段提交之后我们再来看一下SQL更新语句的执行流程 。
7. SQL更新语句的执行总结——终版

文章插图
- 客户端发送更新命令到MySQL服务器,经过处理连接、解析优化等步骤;
- Server层向InnoDB存储引擎要id=1的这条记录;
- 存储引擎先从缓存中查找这条记录,有的话直接返回,没有则从磁盘加载到缓存中然后返回;
- Server层执行器修改这条记录的name字段值;
- 存储引擎更新修改到内存中;
- 存储引擎记录redo日志,并将状态设置为prepare状态;
- 存储引擎通知执行器,修改完毕,可以进行事务提交;
- Server先写了个binlog;
- Server提交事务;
- 存储引擎将redo日志中和当前事务相关的记录状态设置为commit状态 。
【一条SQL更新语句是如何执行的?】
推荐阅读
- 腾讯QQ macOS版6.8.8.6517测试版更新:表情面板新增GIF表情Tab
- 天下长河|《天下长河》更新慢不够看?别慌,6部重磅大剧将播,总有你的菜
- lazada|“卖爆”东南亚的国货美妆,趟出了一条出海路
- flink sqlserver flinksql语法
- 功能齐全的 MySQL 数据库管理工具
- 于魁智|“京剧界最好的一条嗓子”于魁智:我没有离婚,妻子还是原配
- 剑网3|LML就一个职业,Mlxg脾气太差,直言就像一条狗,北枫还挺厉害
- 许敏|相亲相爱一家人!姚策堂嫂更新言宝旧照,一家人忙碌打包很温馨
- 世界排名更新了 羽毛球 世界排名
- SQLSERVER如何分离和附加数据库
