2023年8月3日发(作者:)

mysqlupdate机制_【MySQL】⼀条update语句的⽣命周期最近看到⼀个关于MySQL的⾯试题:⼀条update语句在MySQL中的⽣命周期是怎么样的?我觉得这个问题很有意义,看似简单,实际上考察的是对MySQL整个架构体系的⼀个理解。那么我们就来整理⼀下⼀条SQL在MySQL中的整个历程。⼀、Server层阶段:连接器:⾸先当然是要跟MySQL服务端建⽴连接,那么连接器主要做的事情就是握⼿,建⽴连接⼯作线程,判断最⼤连接数,权限验证,和维持连接(循环)分析器:对SQL进⾏语法分析,判断语句类型,是否存在语法错误,以及⽤户对表的访问权限优化器:对SQL进⾏语句优化,选择索引,⽣成执⾏计划执⾏器:根据优化器⽣成的执⾏计划,调⽤存储引擎的API执⾏SQL⼆、存储引擎层(InnoDB)阶段:事务执⾏阶段⾸先判断 update 语句涉及的数据页是否存在于 innodb buffer pool(BP) 中,如果不存在,则从磁盘中读取该⾏记录所在的数据页并加载到BP缓冲池中,具体加载过程:⾸先通过 space id 和 page no 哈希计算之后把索引页加载到BP中然后判断BP中的 free list 是否有空闲可⽤,没有则需要通过 checkpoint 机制对 flush list 中的脏页进⾏刷盘或者将 lru list 的 old list ⾥⾯copy 数据页到 free list 中,并加载到 old list 的头部(midpoint);通过⼆分法查找到该页对应要修改的记录,并加上排他锁(关于锁的⼜可以写⼀篇⽂章,这⾥简单说明下,加锁前会判断是否锁等待和死锁)接着先写undo log,将修改前的记录写⼊undo log中,并写⼊事务id到这条记录,然后使⽤回滚指针指向undo log中的修改前的⾏,⽤于回滚数据和实现MVCC(关于MVCC⼜可以写⼀篇⽂章)接着写redo log buffer:判断redo log buffer是否够⽤,不够⽤会等待,然后将记录在BP中进⾏update,并将修改后的字段值写⼊redolog buffer中,同时还会LSN加上当前redo log写⼊的长度(写⼊长度为length的redo log,LSN号就回加上length)。接着写binlog cache:修改的信息,会以event的格式,记录到binlog cache中接着写change buffer:将update语句对⼆级索引上做的修改,写⼊到 change buffer,等到下次有其他sql需要读取该⼆级索引的时候,再去与⼆级索引做merge(change buffer是innodb中的重要特性,主要还是对磁盘IO的优化,将随机IO转化为顺序IO)到这⾥为⽌,数据在内存中就更新完成了,BP中对应的数据页也成了脏页。事务提交阶段事务的COMMIT分为prepare阶段与commit阶段。事务的COMMIT操作,在Server层和InnoDB引擎层之间采⽤的是内部XA;作⽤是为了保证redo log和binlog的原⼦性。prepare阶段(redo):写⼊redo log处于prepare状态,并写⼊事务的xid;将redo log buffer刷到redo log磁盘⽂件中,⽤于carsh recovery。(刷盘的⽅式由innodb_flush_log_at_trx_commit 参数决定)commit阶段(binlog):binlog write&fsync:执⾏器将binlog cache⾥的完整事务和redo log prepare中的xid写⼊binlog中(在这⼀步,binlog cache⾥⾯的的event会由dump线程发给slave的I/O线程,同时执⾏fsync刷盘,然后清空binlog cache)redo log commit:这⾥只是在redo log⾥标记commit事务提交还会涉及到redo group commit 和 binlog group commit 就不在这⾥展开讲了,这个后⾯专门开⼀篇⽂章来分析。到⽌,⼀条update语句的⽣命周期就结束了。

2023年8月3日发(作者:)

mysqlupdate机制_【MySQL】⼀条update语句的⽣命周期最近看到⼀个关于MySQL的⾯试题:⼀条update语句在MySQL中的⽣命周期是怎么样的?我觉得这个问题很有意义,看似简单,实际上考察的是对MySQL整个架构体系的⼀个理解。那么我们就来整理⼀下⼀条SQL在MySQL中的整个历程。⼀、Server层阶段:连接器:⾸先当然是要跟MySQL服务端建⽴连接,那么连接器主要做的事情就是握⼿,建⽴连接⼯作线程,判断最⼤连接数,权限验证,和维持连接(循环)分析器:对SQL进⾏语法分析,判断语句类型,是否存在语法错误,以及⽤户对表的访问权限优化器:对SQL进⾏语句优化,选择索引,⽣成执⾏计划执⾏器:根据优化器⽣成的执⾏计划,调⽤存储引擎的API执⾏SQL⼆、存储引擎层(InnoDB)阶段:事务执⾏阶段⾸先判断 update 语句涉及的数据页是否存在于 innodb buffer pool(BP) 中,如果不存在,则从磁盘中读取该⾏记录所在的数据页并加载到BP缓冲池中,具体加载过程:⾸先通过 space id 和 page no 哈希计算之后把索引页加载到BP中然后判断BP中的 free list 是否有空闲可⽤,没有则需要通过 checkpoint 机制对 flush list 中的脏页进⾏刷盘或者将 lru list 的 old list ⾥⾯copy 数据页到 free list 中,并加载到 old list 的头部(midpoint);通过⼆分法查找到该页对应要修改的记录,并加上排他锁(关于锁的⼜可以写⼀篇⽂章,这⾥简单说明下,加锁前会判断是否锁等待和死锁)接着先写undo log,将修改前的记录写⼊undo log中,并写⼊事务id到这条记录,然后使⽤回滚指针指向undo log中的修改前的⾏,⽤于回滚数据和实现MVCC(关于MVCC⼜可以写⼀篇⽂章)接着写redo log buffer:判断redo log buffer是否够⽤,不够⽤会等待,然后将记录在BP中进⾏update,并将修改后的字段值写⼊redolog buffer中,同时还会LSN加上当前redo log写⼊的长度(写⼊长度为length的redo log,LSN号就回加上length)。接着写binlog cache:修改的信息,会以event的格式,记录到binlog cache中接着写change buffer:将update语句对⼆级索引上做的修改,写⼊到 change buffer,等到下次有其他sql需要读取该⼆级索引的时候,再去与⼆级索引做merge(change buffer是innodb中的重要特性,主要还是对磁盘IO的优化,将随机IO转化为顺序IO)到这⾥为⽌,数据在内存中就更新完成了,BP中对应的数据页也成了脏页。事务提交阶段事务的COMMIT分为prepare阶段与commit阶段。事务的COMMIT操作,在Server层和InnoDB引擎层之间采⽤的是内部XA;作⽤是为了保证redo log和binlog的原⼦性。prepare阶段(redo):写⼊redo log处于prepare状态,并写⼊事务的xid;将redo log buffer刷到redo log磁盘⽂件中,⽤于carsh recovery。(刷盘的⽅式由innodb_flush_log_at_trx_commit 参数决定)commit阶段(binlog):binlog write&fsync:执⾏器将binlog cache⾥的完整事务和redo log prepare中的xid写⼊binlog中(在这⼀步,binlog cache⾥⾯的的event会由dump线程发给slave的I/O线程,同时执⾏fsync刷盘,然后清空binlog cache)redo log commit:这⾥只是在redo log⾥标记commit事务提交还会涉及到redo group commit 和 binlog group commit 就不在这⾥展开讲了,这个后⾯专门开⼀篇⽂章来分析。到⽌,⼀条update语句的⽣命周期就结束了。