【发布时间】:2011-03-02 06:46:21
【问题描述】:
我只是想了解通过事务解决的“更新丢失”的含义。
请看下面两个事务,我使用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 视为:
- 更新值1000取决于读取的count,即select。
- 更新值 50 取决于另一个读取(与 session1 不冲突)。
所以,这是典型的读写依赖。
session1 (T1) 提交并再次执行'select count from counter where id=0'后,计数将是1000。我想知道是不是更新丢失 还是没有?如果不是为什么?如果我没记错的话,在任何隔离级别都将避免最后的任何更新。
一种可能的解决方法是使用“从 id = 0 的计数器中选择计数进行更新;”在第 2 步,这相当于在记录上添加 xlock,因此 T2 将被阻塞。所以这是串行执行的[T1,T2]。
这是 Innodb 的(已知)错误吗?注意,这不等价于执行[T2,T1],因为T1会按照这个顺序读取50个其他0,最终的结果会不一样。
谢谢
【问题讨论】:
-
您需要描述您的实际任务,以便我们为您提供如何解决它的示例场景。
-
@zerkms,我只是想明白“更新丢失”是什么意思。
-
在 Session2-commit 和 Session1-commit 之间,count 的值为 50,但在 Session1-commit 之后,它将就像从未更新到 50 一样。所以我们可以称更新丢失'。
-
我认为更新丢失了,从我发现的情况来看,在这种情况下(select * from ..),innodb 将执行非锁定读取。我们至少添加一个共享锁。
标签: mysql database concurrency