Mysql 更新一条数据的过程
程序员文章站
2022-04-09 22:57:40
...
mysql固然是俺们后台同学每天都会使用接触到的关系型数据库,而我们通过标准的sql语句当然可以很熟练的操作mysql实现常规的CRUD。但是如果突然有一天,领导问你一个update一句怎么执行的,如果执行update语句的时候突然宕机了,数据怎么恢复。。。。。。感觉一下子就涉及到了俺的知识盲区,然而,学而知不足,不懂就学嘛。写个文章记录一下,我对于mysql 最常用的 update 怎么执行的理解
下图是从视频截图的,简单介绍了下innoDB的大致结构
使用innoDB引擎的mysql的对于update的执行概览图,大致的执行计划是:
比如 执行一个简单的更新操作:
update A set a=a+1 where id=6;
操作顺序
- 查找记录:执行器先找引擎取id=6这一行。id是主键,引擎直接用树搜索找到这一行。如果id=1这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回;
- 执行器拿到引擎返回的行数据,把num改为+1,得到新的一行数据,再调用引擎接口写入这行新数据;
- 引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处于prepare状态;
- 引擎告知执行器,我执行完成了,你随时可以调我的接口提交事务了;
- 执行器生成这个操作的binlog,并把binlog写入磁盘。
- 执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交commit状态,更新完成。
redolog 的简单介绍:redo log用于保证crash-safe能力。innodb_flush_log_at_trx_commit这个参数设置成1的时候,表示每次事务的redo log都直接持久化到磁盘。这个参数我建议你设置成1,这样可以保证MySQL异常重启之后数据不丢失。
- 先写 redo log 直接提交,然后写 binlog,假设写完 redo log 后,机器挂了,binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 bingog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。
- 先写 binlog,然后写 redo log,假设写完了 binlog,机器异常重启了,由于没有 redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。