这个更新丢失了吗?

时间:2011-03-02 06:46:21

标签: mysql database concurrency

我只想了解“更新丢失”的含义,这是通过交易解决的。

请看下面两个事务,我使用mysql 5.5.8和innodb存储引擎:

create table counter (what varchar(5), id integer, count integer, primary key (id));
insert into counter values ('total', 0, 0);

      session 1 (T1)                       session 2(T2)
 -------------------------------------------------------------------------
0                               |           begin;
 -------------------------------------------------------------------------
1           begin;              |        
 -------------------------------------------------------------------------
2   select count from  counter  |
    where id = 0;               |
 -------------------------------------------------------------------------
3                               |   update counter set count = 50 
                                |   where id = 0; 
 -------------------------------------------------------------------------
4                               |   commit;
 ------------------------------------------------------------------------
5  update counter set count     |
   = 1000 where id = 0;         |
 -------------------------------------------------------------------------
6           commit;             |        
 -------------------------------------------------------------------------

您可以将值1000和50视为:

  1. 更新值1000取决于读取计数,即选择。
  2. 更新值50取决于另一个读取(与session1不冲突)。
  3. 因此,这是典型的读写 - 写入依赖性。

    session1(T1)之后提交并执行'从计数器中选择计数,其中id = 0',计数将为1000.我想知道它是否更新丢失或不?如果不是为什么?如果我记得正确,任何类型的更新都将在任何隔离级别中避免。

    其中一个可能的解决方法是使用“从计数器中选择计数,其中id = 0表示更新;”在步骤2,这相当于在记录上添加xlock,因此T2将被阻止。所以这是串行执行的 [T1,T2]

    这是Innodb的(已知)错误吗?注意,这不等于执行 [T2,T1] ,因为T1将使用此序列读取50其他0,并且最终结果将不同。

    由于

3 个答案:

答案 0 :(得分:2)

是的,当然更新丢失了。对于外部世界,您的交易仅在提交时才“真正”执行。对于第三方,您的架构对应于:

  1. 会话2将ID为0的计数器更新为50
  2. 会话1将ID为0的计数器更新为1000
  3. 你实际上甚至不需要交易:交易没有区别。如果你的会话1选择AFTER会话2进行更新,它们就很重要。在这种情况下,对于事务,会话1将读取值0,但没有事务,它将读取值50。

答案 1 :(得分:0)

这是因为INNODB默认隔离级别REPEATABLE READ

答案 2 :(得分:0)

是的,您的情况正是丢失更新意味着什么。在postgresql中,T1将被dbms中止以防止更新丢失。