四川省建设厅官方网站贵州企业网站建设价格
news/
2025/9/30 22:52:49/
文章来源:
四川省建设厅官方网站,贵州企业网站建设价格,永久免费微商城小程序,自在源码网文章目录 1 问题描述2 验证2.1 验证猜想12.2 验证猜想2 3 结论4 mysql 为什么这么设计呢#xff1f; 1 问题描述
创建一张表t#xff0c;插入一行数据
mysql CREATE TABLE t (
id int(11) NOT NULL primary key auto_increment,
a int(11) DEFAULT NULL
) ENGINEInnoDB… 文章目录 1 问题描述2 验证2.1 验证猜想12.2 验证猜想2 3 结论4 mysql 为什么这么设计呢 1 问题描述
创建一张表t插入一行数据
mysql CREATE TABLE t (
id int(11) NOT NULL primary key auto_increment,
a int(11) DEFAULT NULL
) ENGINEInnoDB;
insert into t values(1,2);现在表t中已经有id 1a2这一行 执行更新语句更新id1这一样将a的值修改为2逻辑上值不变 update t set a 2 where id 1;可以看到返回结果0 rows affected。 仅从现象上看mysql在处理这个条sql语句时可能是以下三种情况
命令执行到server层返回因为执行更新之前需要先读出数据server层的执行器拿到id1的这一行发现a2于是不会调用InnoDB修改行字段的接口直接返回。没加写锁命令执行到Innodb层返回server层调用了InnoDB修改行字段的接口InnoDB对数据加上了写锁然后进行当前读读出最新的a的值是2发现与旧值相同于是不更新直接返回。加了写锁没执行更新InnoDB认真执行了修改操作InnoDB对数据加上了写锁然后进行当前读读出最新的a的值是2发现与旧值相同但是还是执行了一次更新操作将2赋值给a然后记录到redo log中经过两阶段提交结束事务。也就是一个完整的正常的更新过程
2 验证
2.1 验证猜想1
猜想1很好验证如果没加写锁让事务A和事务B并发的执行更新语句如果后执行的事务没有被阻塞则证明猜想1正确。
时间事务A事务Bt0begin;t1begin;t2update t set a 2 where id 1;t3update t set a 2 where id 1;t4commit;t5commit;
事务A
事务B 事务B的update语句被阻塞等到事务A commit后才会提交。说明update过程中是加锁了的猜想1不正确。
2.2 验证猜想2
猜想2是加锁但是没有执行更新逻辑。可以采用InnoDBMVCC机制来验证MVCC就是在事务整个过程中会拿到一致性视图对普通读进行复用达到可重复读的隔离级别。
时间事务A事务Bt0begin;t1select * from t where id 1 // (1,2)t2begin;t3update t set a 3 where id 1;t4commit;t5select * from t where id 1 // (1,2)t6commit;
由于MVCC的机制且InnooDB引擎默认设置的隔离级别是可重复度所以事务A在开始的时候就会创建一致性视图整个事务过程中进行复用。 所以第一句select和第二句select查到的都是(1,2)因为事务B的更新对事务A是不可见的。 接下来我们对事务A再加一条更新的sql语句:
时间事务A事务Bt0begin;t1select * from t where id 1 // (1,2)t2begin;t3update t set a 3 where id 1;t4commit;t5update t set a 3 where id 1;t6select * from t where id 1 // (1,3)commit;
t5时刻事务A执行了更新更新语句是当前读不是快照读所以更新语句会读取到当前表中最新的数据事务A读出来此时a3而自己要更新的也是3旧值与要更新的新值相同根据猜想2事务A此次更新不会执行。也就是InnoDB 的undo log中保留的行数据还是事务B更新的版本而这个版本的更新是对事务A是不可见的也就是后续的select语句读出来的结果应该还是(1,2)。但此时事务A读出来的结果却是(1,3)。说明猜想2错误InnoDB确实做了更新并记录了undo log 和 redo log。
3 结论
mysql要更新一条行记录是即使这条行记录的旧值与要更新的新值相同mysql也会按部就班地进行更新。
4 mysql 为什么这么设计呢
我想有以下几点原因
数据一致性InnoDB会按照用户要求的进行操作即使这个操作显而易见地可以优化比如要更新的值与旧值相同。这是为了保证数据一致性如果让InnoDB决定哪些操作需要跳过可能会导致数据不一致。事务因为update这条语句可能只是这个事务的其中一环如果这个语句不按照正常的更新流程走再发生事务回滚时就回滚不了。触发器如果有表触发器比如只要update执行了就触发的触发器如果innodb自行跳过这些触发器就不会执行。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/923320.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!