sql更新是如何执行的?
2018-05-09 本文已影响0人
swoft_
update from set a = 1 where id = 1
首先看一下一张图(图片来自 sql查询是如何执行的?)
image.png和查询类似,也会走同样的逻辑。
- 创建连接。
- 清除缓存。
- 分析器 分析语法,检查表和字段是否存在。
- 优化器,决定是否使用索引,使用哪一个索引。
- 执行器。主要区别在这一层,下面说说我理解的具体区别。
与查询流程不同的是,更新涉及到redo_log (重做日志) 和 binlog(归档日志)
redo log
如果更新数据直接修改磁盘数据,会首先找到磁盘中的数据,然后在修改磁盘中的数据,io成本会很高。所以mysql更新不会直接修改逻辑数据,而是先写到内存中,然后等mysql空闲之后,会同步到硬盘。
- 作用在存储引擎上,innodb 特有的。
- redo log 大小是固定的。类似一个环,每次写满之后会强制刷新,从头开始写。
- redo log 会保证即使数据库发生异常,数据也不会丢失。
- 物理日志,记录了在哪个数据页上的修改
binlog
作用在service层,是mysql的日志,所有存储引擎都可以使用。记录了所有增删改的逻辑日志。
记录方式 statement 记录sql语句 row 记录每一行数据的改动,mixed(混合模式) mysql会根据具体的sql来决定按照什么方式进行记录
执行器的执行流程
update t set a=a+1 where id=1;
- 调用存储引擎接口,找到id=1这一条记录。如果数据在内存中直接返回,否则先从磁盘中读到内存,然后返回
- 执行器拿到结果,进行+1操作,再调用存储引擎接口写入新数据。
- 存储引擎将这行数据更新到内存,同时记录redo log(perpare) 然后返回成功
- 执行器生成binlog,把binlog写入磁盘。
- 调用引擎提交事务,把redo log 改成提交状态(commit)。更新完成
两阶段提交
上面redo log 2次写入被称为两阶段提交。
redo log 保证了及时异常重启,也会把数据刷新到磁盘中。binlog主要适用于数据备份的。
目的:因为redo log 和binlog 是2个完全不同的东西,一个是存储引擎实现的一个是数据库本身实现的。所以为了保证redo log 和binglog 的一致性,引入了两阶段提交。
uodo log 只是为了回滚使用,比如把name=‘a’ 修改为name = ‘b’ ,那么undo日志就会用来存放name=’a’的记录,如果这个修改出现异常,可以使用undo日志来实现回滚操作,保证事务的一致性。