SQL在MySQL数据库中是如何执行的
查询语句的一套执行流程,更新语句也会同样的走一步,下边我们在对照上次文章中的图来简单的看一下:
" data-height="600" data-width="800" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d529960ec1dd496ca90860641bcaa093~tplv-k3u1fbpfcp-watermark.image" class="aligncenter">
首先,在执行语句前要先连接数据库,这是第一步中连接器的工作,前面我们也说过,当一个表有更新的时候,跟这个表有关的查询缓存都会失效,所以我们一般不建议十月查询缓存。
接下来,分析器会经过语法分析和词法分析,知道了这是一条更新语句后,优化器决定要使用哪一个索引,然后执行器负责具体的执行,先找到这一行,然后做更新。
与查询语句更新不同的是,更新流程还涉及两个重要的日志,这个我们在前边的文章中也有专门的介绍,有兴趣的可以找一下上周的文章《MySQL的两个日志系统》,这里就不多做介绍了。
下边通过一个简单的例子来分析一下更新操作的流程。
我们先创建一张表,这个表有主键ID和一个整型字段c:
mysql> create table demo T (ID int primarty ,c int);复制代码
然后将ID=2的这一行的值加1
mysql> update table demo set c = c + 1 where ID = 2;复制代码
接下来我们来看看update语句的执行流程,图中浅色框表示在存储引擎中执行的,神色框代表的是执行器中执行的。

我们可以看到最后的时候,写redolog的时候分了两步,prepare和commit,这就是我们常说的“两阶段提交”。
为什么日志需要“两阶段提交”?
由于redo log和binlog分别是存储引擎和执行器的日志,是两个独立的逻辑,如果不用两阶段提交,无论先提交哪个后提交哪个都会存在一些问题。我们这里也借助上边的例子看一下,假设当前ID=2的这一行值为0 ,在update的过程中写完了第一个日志后,第二个日志还没写期间发生了crash,会怎么样?
- 先写redolog后写binlog。假设redolog写完,binlog还没写完,MySQL进程异常重启了。我们知道,redolog写完以后,系统即使崩溃了,也可以将数据恢复,所以在MySQL重启后,这一行回被恢复成1。由于binlog没写完就crash,这时候binlog里面是没有这个语句的,因此之后备份日志的的时候,存起来的binlog日志也没有这一条语句。当我们需要通过binlog来恢复数据的时候,由于binlog丢失了这条语句,恢复出来的这一行的值就是0,与原库的值不一样啦。
- 先写binlog后写redo log。如果写完buglog之后,redo log还没写完的时候发生 crash,如果这个时候数据库奔溃了,恢复以后这个事务无效,所以这一行的值还是0,但是binlog里已经记载了这条更新语句的日志,在以后需要用binlog来恢复数据的时候,就会多了一个事务出来,执行这条更新语句,将值从0更新成1,与原库中的0就不同了。
我们可以看到如果不使用“两阶段提交",那么数据库的状态就会和用日志恢复出来的库不一致。虽然平时用日志恢复数据的概率比较低,但是用日志最多的还是扩容的时候,用全量备份和binlog来实现的,这个时候就可能导致线上的主从数据库不一致的情况。
您可能感兴趣的文章
- 12-31hiredis从安装到项目实战操作
- 12-31phpmyadmin登录时怎么指定服务器ip和端口
- 12-31MySQL线上死锁分析实战
- 12-31MySQL 触发器的使用和理解
- 12-31MySQL 字段默认值该如何设置
- 12-31Redis主从同步配置的方法步骤(图文)
- 12-31MySQL 字符串拆分操作(含分隔符的字符串截取)
- 12-31redis 交集、并集、差集的具体使用
- 12-31MySQL精讲之二:DML数据操作语句
- 12-31PostgreSQL判断字符串是否包含目标字符串的多种方法


阅读排行
推荐教程
- 12-23PL/SQL登录Oracle数据库报错ORA-12154:TNS:无法解析指定的连接标识符
- 12-23使用imp和exp命令对Oracle数据库进行导入导出操作详解
- 12-11mysql代码执行结构实例分析【顺序、分支、循环结构】
- 12-08添加mysql的用户名和密码是什么语句?
- 12-05mysql的事务,隔离级别和锁用法实例分析
- 12-23详解Oracle游标的简易用法
- 12-20PhpMyAdmin出现错误数据无法导出怎么办?
- 12-19Redis中实现查找某个值的范围
- 12-15浅析mysql迁移到clickhouse的5种方法
- 12-15CentOS7 64位下MySQL5.7安装与配置教程




