一条更新语句是如何执行的
和查询很像,连接器,分析器,优化器,执行器,不过和查询不同的是,更新流程还涉及到日志模块。
redolog
当有一条记录需要更新的时候,Innodb引擎就会先把记录写到redo log里面,并更新内存,这个时候更新就完成了,同时innodb引擎会在适当的时候,将这个操作记录更新到磁盘里面,在系统比较空闲的时候。
这个就是WAL技术(write ahead logging),关键点就是先写日志,在写磁盘。
innoDb的redo log是固定大小的,从头开始写,往复循环,写满的时候就必须要更新库里,删除部分记录才能继续写入。这样即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe
binlog
redolog日志是innodb引擎特有的日志,其他引擎无法使用,server层自己的日志称为 binlog(归档日志),但是bin log并不具有cash-safe能力。
二者的区别
redo是innodb引擎特有的,binlog是mysql的server层实现的,所有引擎都能用
redolog是循环写的,binlog是可以追加写入,追加写是指binlog文件写到一定大小后,会切换到下一个,并不会覆盖之前的日志。
redo是物理日志,记录的是 “某个数据越上做了什么修改”,binlog是逻辑日志,有两种格式statment格式记录sql语句,row格式记录更新前后行的内容。
详细看下执行器在执行update语句的流程。
update T set c=c+1 where ID=2;
执行器先找引擎取id=2这一行,引擎直接用树搜索找到这一行,如果这一行本来就在内存中,就直接返回给执行,否则需要先从磁盘读入内存,然后再返回。
执行器拿到引擎给的行数据,把这个值加上1,比如原来是n,现在就是n+1得到新的行数据,在调用引擎接口写入这行新数据。
引擎将这行数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redolog处于prepare状态。然后告知执行器执行完成了,随时可以提交事务。
执行器生成这个操作的binlog,并把binlog写入磁盘
执行器调用引擎的提交事务接口,引擎把刚刚写入redo log改成提交状态,更新完成。
最后三步就是两阶段提交,其目的和事务类似就是为了让两个日志文件对应的保持一致,恢复的数据保持一致。如果有任意一个日志在生成工程中出现异常那么两个日志里关于更新这次都将不能成功生成,这次更新操作也会失败回滚。
评论区