插入一行时的竞争条件

时间:2014-01-18 06:41:49

标签: mysql sql database rdbms race-condition

我有3张桌子:

Counters: ID, ItemCatalogID, CurrentCounter

Item: ID, ItemCatalogID, Name, Description, OtherValue

ItemCatalog: ID, Name, Description

计数器表包含项目目录的CurrentCounter,当我插入一行时,我必须查询DB,获取相应目录的当前计数器,然后将此值更新为1并将此值用于OtherValue字段。

例如:

update Counters set CurrentCounter = CurrentCounter + 1 where ItemCatalogID = 100;
select CurrentCounter into v from Counters where ItemCatalogID = 100;
insert into Item(ItemCatalogID, Name, Description, OtherValue) values (100, 'MyItem', 'Short Description', v);

但我想知道竞争条件会发生吗?如何改进我的解决方案?

1 个答案:

答案 0 :(得分:1)

是的,你的情况可能会引发竞争条件。

你需要这些柜台吗?您可以使用适当的查询轻松替换它们:

SELECT COUNT(*) FROM ItemCatalog WHERE ID=100;
SELECT COUNT(*) FROM Item WHERE ID=100;

对于连续的字段内容,建议使用AUTO_INCREMENT列。但似乎这不适用于您的情况。

但是,您可以使用上面的COUNT(*)方法:

insert into Item(ItemCatalogID, Name, Description, OtherValue) values (100, 'MyItem', 'Short Description', (select count(*) from Item where ID=100));

您可能需要为表格中的一个出现别名:

insert into Item(ItemCatalogID, Name, Description, OtherValue) values (100, 'MyItem', 'Short Description', (select count(*) from Item AS I where ID=100))

这只需一步即可执行,您无需担心竞争状况。

如果由于某些原因无法更改,则还有另一种解决方案:使用表锁定。

使用

添加语句前缀
LOCK TABLES Counters WRITE, Item WRITE

并以

为后缀
UNLOCK TABLES

以获得对它们的独占写入权限。