mysql多字段修改update_update 修改单表的多个字段,造成数据混乱

    

作者:杨建,知数堂优秀校友。
原文:https://www.cnblogs.com/keme/p/13101115.html

1、问题描述1.1、模拟问题现象1.2、问题故障原因1.3、解决故障2、问题总结2.1、快照读(select)2.2、当前读3、延伸思考

1、问题描述

今天 QQ群里在讨论一个问题,在某个环境里面,需要修改单个表的多个字段,造成了数据混乱,跟理想修改的数据不一致。

1.1、模拟问题现象

# 注意: 创建的表没有主键,且 t1 表是 innodb 引擎

![img](./image/update 修改多字段,造成数据混乱/1.png)

修改的条件是a=2,为啥修改的结果是(3,13),不应该是(3,12)吗?

是不是很多人以为修改的结果是(3,12),是不是感觉数据是乱的,如果一条数据改回正常还是挺简单,关键数据量很多改的就费劲了啊,时间还长。

1.2、问题故障原因

因为 update 是当前读,读取的是记录数据的最新版本

update t1 

1.3、解决故障

# 我先改回原来数据

![img](./image/update 修改多字段,造成数据混乱/2.png)

2、问题总结

我们需要知道一些相关原理: 快照读,当前读

2.1、快照读(select)

执行select的时候,innodb默认会执行快照读,快照读,也就是读取快照的数据,数据虽然是一致的,但是数据是历史数据。

快照读:只是简单的 select ,不包括 select … lock in share mode, select … for update

2.2、当前读

  • select … lock in share mode

  • select … for update

  • insert

  • update

  • delete

当你执行这几个操作的时候默认会执行当前读会加锁,也就是会读取最新的记录,也就是别的事务提交的数据你也可以看到。

update 执行当前读,然后把返回的数据加锁,之后执行update。

加锁是防止别的事务在这个时候对这条记录做什么,默认加的是排他锁,也就是只允许读,其他都不可以,这样就可以保证数据不会出错了。

3、延伸思考

上面的情况是:

  • innodb 引擎

  • 表中无主键

如果表中有主键,或者是其他引擎,正确操作,请看下面的大神文章

//imysql.com/2008_06_17_sth_about_update_duplicate_key

全文完。

Enjoy MySQL :)


由叶老师主讲的知数堂「MySQL优化课」课程早已升级到MySQL 8.0版本了,现在上车刚刚好,扫码开启MySQL 8.0的修行之旅吧。

eb578f3ee0a73b15dfdbcd5158195c3e.png


另外,叶老师在腾讯课堂《MySQL性能优化》精编版第一期已完结,本课程讲解读几个MySQL性能优化的核心要素:合理利用索引,降低锁影响,提高事务并发度

下面是自动拼团的二维码直接享受组团价

56c5fa4555ad4884984ec827e41b36a5.png