查询语句的一套执行流程,更新语句也会同样的走一步,下边我们在对照上次文章中的图来简单的看一下:
" class="lazyload" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d529960ec1dd496ca90860641bcaa093~tplv-k3u1fbpfcp-watermark.image" data- style="max-width:90%" data- style="max-width:90%">
首先,在执行语句前要先连接数据库,这是第一步中连接器的工作,前面我们也说过,当一个表有更新的时候,跟这个表有关的查询缓存都会失效,所以我们一般不建议十月查询缓存。
接下来,分析器会经过语法分析和词法分析,知道了这是一条更新语句后,优化器决定要使用哪一个索引,然后执行器负责具体的执行,先找到这一行,然后做更新。
与查询语句更新不同的是,更新流程还涉及两个重要的日志,这个我们在前边的文章中也有专门的介绍,有兴趣的可以找一下上周的文章《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,会怎么样?
我们可以看到如果不使用“两阶段提交",那么数据库的状态就会和用日志恢复出来的库不一致。虽然平时用日志恢复数据的概率比较低,但是用日志最多的还是扩容的时候,用全量备份和binlog来实现的,这个时候就可能导致线上的主从数据库不一致的情况。
相关免费学习推荐:mysql视频教程
Atas ialah kandungan terperinci SQL在MySQL数据库中是如何执行的. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!