【问题标题】:MySQL 'REPEATABLE READ' transaction unexpected behaviorMySQL 'REPEATABLE READ' 事务意外行为
【发布时间】:2017-07-28 20:00:14
【问题描述】:

MySQL 事务的默认隔离级别是“Repeatable Read”。

根据另一个stackoverflow问题( Difference between read commit and repeatable read) “可重复读是更高的隔离级别,即除了保证读提交级别之外,它还保证任何读取的数据都不能改变,如果事务再次读取相同的数据,它会找到之前读取的数据,未更改,可供阅读。”

这是我的测试数据库;

mysql> select * from people;
+------+---------+
| name | howmany |
+------+---------+
| alex |     100 |
| bob  |     100 |
+------+---------+

slow.sql

START TRANSACTION;

SELECT @new_val := howmany FROM people WHERE name = 'alex';
SELECT SLEEP(10);
SET @new_val = @new_val - 5;
UPDATE people SET howmany = @new_val WHERE name = 'alex';

COMMIT;

fast.sql

START TRANSACTION;

SELECT @new_val := howmany FROM people WHERE name = 'alex';
--  SELECT SLEEP(10);
SET @new_val = @new_val - 5;
UPDATE people SET howmany = @new_val WHERE name = 'alex';

COMMIT;

如果我运行 slow.sql,在它返回之前我会多次运行 fast.sql。 fast.sql 将打印 95、90、85....

我认为可重复读取隔离级别应该使 fast.sql 无法运行,或者我误解了“可重复读取”。

我从 Ubuntu 16.10 运行 MySQL 5.7。

非常感谢。

【问题讨论】:

    标签: mysql sql transactions


    【解决方案1】:

    如果没有错,那么Repeatable Read 谈论的是同一事务中的一致性读取,而不是其他事务。来自MySQL Documentation

    • 可重复读取

    这是 InnoDB 的默认隔离级别。一致的读取 在同一个事务中读取第一个建立的快照 读。这意味着,如果您发出几个普通(非锁定)SELECT 同一事务中的语句,这些 SELECT 语句是 也相互一致。

    【讨论】:

      【解决方案2】:

      可重复读取隔离级别可确保单个事务内的一致性。您正在执行多个事务。对于您期望的行为,您需要查看锁定读取。请参阅此处了解更多信息。 https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html#isolevel_repeatable-read

      【讨论】:

        【解决方案3】:

        如果您的交易过程中某些数据被外部进程更改,则不会对所述交易中读取的数据产生任何影响。

        我不知道 fast.sql 会因为这种隔离级别(或任何隔离)而无法运行。

        【讨论】:

          猜你喜欢
          • 2013-12-22
          • 2019-04-16
          • 2019-12-14
          • 2012-01-07
          • 2017-10-06
          • 2022-09-23
          • 1970-01-01
          • 1970-01-01
          • 2018-11-23
          相关资源
          最近更新 更多