MYSQL学习笔记--SQL更新语句的执行
MYSQL更新语句是这样子的:
mysql> update T set c=c+1 where ID=2;
更新语句跟查询语句走的流程是一样的:
跟查询一样,连接器----》查询缓存—》分析器----》优化器—》执行器。
与查询不同的地方,多了两个日志模块redolog和binlog.
redo log
由于每次操作如果每次对数据库的操作都写入磁盘进行持久化的,整个操作的IO成本,查找成本都很高。所以MYSQL设计者就用了WAL技术(Write-Ahead Logging).原理就是先写日志,在不忙的时候在写磁盘,提高效率。
INNODDB先把记录写入日志,更新内存,然后直接返回。redo log的大小是固定的,比如可以配置一组4个,每个1GB,总共用4G的缓存空间。同时redo log采用了循环缓冲区的数据结构,如下图:
当write_pos 等于check point的时候,表示缓冲区已经满了,需要先清理一下缓冲区。
有了这个设计,就可以保证crach-safe,当数据库异常重启的时候,之前提交的事物记录都不会丢失。
binlog
binlog(归档日志),是MYSQL SERVER层,不具备crach-safe能力。redo log是innodb拥有的。
不同的地方:
1 redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
2 redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
3 redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
更新语句执行流程:
1 执行器找引擎拿到ID=2这一行,如果在内存,直接从内存里面取。如果不在内存,则从磁盘里面拿。
2 拿到数据后进行+1操作,调用引擎接口写入。
3 引擎写入内存,同时写入redo log,并把状态改为prepare,告知执行器执行完成,可以随时进行提交事物
4 执行器生成binlog,并持久化到磁盘
5 执行器开始提交事务,引擎把redo log的状态从perpare改为commited
两阶段提交
其实就算让两个不同的文件保存逻辑上的一致
顺序不能变,假设:
1 先写 redo log 后写 binlog。
redo log 写完,但是没有写binlog,发生了崩溃。redo log已经写完,binlog没有写。使用binlog备份的时候就会少记录,那么用这个binlog去恢复的时候就会造成丢失数据。
2 先写 binlog 后写 redo log
binlog写完,redolog没有写入就崩溃了。那么这个事物是无效的,因为redolog没有这一条记录,但是binlog却有这条记录,从binlog恢复的时候就会多出一条事物,造成了数据的不一致。
上一篇: 煎牛肉需要注意什么
下一篇: 已知空间两点组成的直线求线上某点的Z值