我有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);
但我想知道竞争条件会发生吗?如何改进我的解决方案?
答案 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
以获得对它们的独占写入权限。