MYSQL 一个特殊需求在不同的MYSQL配置产生不同的结果 与 update 0 是否需要应用程序判断

2024年 1月 24日 60.1k 0

开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题,有需求都可以加群群内,可以解决你的问题。加群请联系微信 liuaustin3 ,(共1910人左右 1 + 2 + 3 + 4 +5) 4群(410+ 默认加5群),另欢迎 OpenGauss 的技术人员加入。

最近有一个需求关于数据的清理的需求,但是这个需求里面有一个部分有一个部分是特殊,也就是在数据清理中,是需要进行数据的导出和导入的,并确定在导入和导出的过程中,导出数据在导出到清理的整个过程中中不能被改变,不能进行commited这些数据需要具有独占性 。

这里要完成这个事情,可以采用对于要迁移的行进行锁定的方法来进行,但锁定的方法可以用 select * from table where 条件 for update; 但问题的重点是, 在不同的MYSQL配置中会产生什么样的结果,不同的结果开发是否能接受的问题。

这里有一个相关的说明和测试的大纲

1   MYSQL innodb_lock_wait_timeout = 更长的时间如 86400 和  innodb_deadlock_detect =ON

2    MYSQL innodb_lock_wait_timeout =3  和  innodb_deadlock_detect = OFF 的情况

在不同场合下,MySQL 在这两边有不同的设置可能性,在一些早期的MYSQL 和互联网的情况下,innodb_deadlock_detect 是为OFF的,并且在 innodb_lock_wait_timeout = 3 也就是不管怎么样,只要出现互斥的状态下,锁超时为3秒,当然这里也包含了死锁的情况,死锁不超过3秒,这里是通过系统锁超时来进行判断的,当然blocked 的情况也是3秒内解决。

但在一些传统性的单位,也有另外的一种配置,innodb_deadlock_detect =ON 并且因为程序编制和需求的原因blocked 的时间都设置的较长并不和互联网设置的相同。 

这里需要在不同的情况下来分析,同样的设置给应用程序带来的不同的问题。

这里先从互联网的方案来说,死锁探测为0 innodb_lock_wait_timeout = 3 当然有的地方更短设置成1秒。具体什么成因这里就不讨论了,同时这里还有一个不同就是隔离级别,我们在每次测试使用不同的隔离级别来看看会有什么影响。

编号 数据库参数 session 隔离 操作类型
1 不探测死锁  3秒解锁 read commit 更新
2 不探测死锁  3秒解锁 repeatable read  更新
3 不探测死锁  3秒解锁 read commit 删除
4 不探测死锁  3秒解锁 repeatable read  删除
5 探测死锁,不解锁 read commit 更新
6 探测死锁,不解锁 repeatable read  更新
7 探测死锁,不解锁 read commit 删除
8 探测死锁,不解锁 repeatable read  删除

1  innodb_lock_wait_timeout = 3  and innodb_deadlock_detect = OFF

innodb_deadlock_detect = OFF
innodb_lock_wait_timeout = 3 

表的状态

mysql> select * from read_table;
+----+------+
| id | name |
+----+------+
|  1 | 1    |
|  2 | 2    |
|  3 | 3    |
|  4 | 4    |
|  5 | 5    |
|  6 | 6    |
|  7 | 7    |
|  8 | 8    |
|  9 | 9    |
+----+------+
9 rows in set (0.00 sec)

1

3

4

这里我们可以看到,整体的操作中,隔离级别对于操作是没有任何影响的,结果都是一样,对于表中的锁定的数据更新失败。

innodb_deadlock_detect = ON
innodb_lock_wait_timeout = 86400

5

6

7

8

通过上面的几个实验,我们可以总结出以下一些结论

在MYSQL 配置中如果使用的 innodb_lock_wait_timeout =3 的配置的情况下,在很短的时间数据库就能判断出BLOCKED 或死锁,在这样的情况下,无论使用什么隔离级别,那么结果都是一样的,都会是锁超时的报错和让你重试的信息。

或者你使用了自动检测死锁,同时将innodb_lock_wait_timeout = 更大的数值,那么你得到的结果就与隔离级别有关了,如果是RR 的情况,你将会获得 update 0 的结果,如果是RC 数据还在的情况下,你会获得update 对应结果的结果,如果相关的行不在的情况下,获得结果也是UPDATE 0 的结果。

另这里也需要注意,在设置 innodb_lock_wait_timeout = 3 的情况下如果blocked 的情况不超过3秒,那么结果还是和 innodb_lock_wait_time=无限大的情况类似。

最终基于以上的结果,应用程序是需要针对程序最终在执行语句后的结果进行判断,到底是 update 0  还是 非0,并根据结果做出相关后续的操作。

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论