首页 > 数据库 > MySQL > 正文

mysql update语句的执行过程详解

2024-07-24 12:54:38
字体:
来源:转载
供稿:网友

以前有过一篇关于MySQL查询语句的执行过程,这里总结一下update语句的执行过程。由于update涉及到数据的修改,所以,很容易推断,update语句比select语句会更复杂一些。

1,准备

创建一张test表

CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `c` int(11) NOT NULL DEFAULT '0' COMMENT '数值', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试表';

插入三条数据

INSERT INTO `test` (`c`) VALUES (1), (2), (3);

2,测试

加入我要把第一条数据的 c 值 加 1,则

UPDATE `test` SET `c` = `c` + 1 WHERE `id` = 1;

按照我们平常的思路,就是找出这条记录,把它的值改好,保存就OK了。

但我们追究一下细节,由于涉及到修改数据,所以涉及到日志了。

3 操作顺序

3.1 查找记录:执行器先找引擎取id=1这一行。ID是主键,引擎直接用树搜索找到这一行。如果id=1这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回;

3.2 执行器拿到引擎返回的行数据,把num改为2,得到新的一行数据,再调用引擎接口写入这行新数据;

3.3 引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处于prepare状态;

3.4 引擎告知执行器,我执行完成了,你随时可以调我的接口提交事务了;

3.5 执行器生成这个操作的binlog,并把binlog写入磁盘。

3.6 执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交commit状态,更新完成。

binlog是MySQL内部实现二阶段提交的协调者,它为每个事务分配一个事务ID: XID
一阶段:
开启事务,redo log 和 undo log已经记录了对应的日志,此时事务状态为prepare
二阶段:

binlog 完成write和fsync后,成功,事务一定提交了,否则事务回滚 发送commit,清除undo信息,刷redo,设置事务状态为completed
  4, 两种日志 4.1 重做日志 redo log

redo log 通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。

一般更新会有如下做法:

直接查询原始数据,立马更新; 先找个临时记事本,做下记录,等不忙的时候/结算时候进行核算更新。

第一种做法在高并发IO的情况下非常的不容乐观。所以一般都会采用第二种方式。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表