mysql - 插入行时的竞争条件

标签 mysql sql database rdbms race-condition

我有 3 个表:

Counters: ID, ItemCatalogID, CurrentCounter

Item: ID, ItemCatalogID, Name, Description, OtherValue

ItemCatalog: ID, Name, Description

Counters 表包含项目目录的 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);

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

最佳答案

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

您是否需要这些计数器?您可以轻松地将它们替换为适当的查询:

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

为了拥有对它们的独占写入权限。

关于mysql - 插入行时的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21201000/

相关文章:

php - 为什么DBF在PHP中会显示为不良记录,而在直接查看时却不会显示为不良记录?

mysql - 使用非索引和复合索引

php - 从 MySQL 数据库中的 css 标签中删除智能引号

sql - 将 XML 与反向路径相结合

mysql - Microsoft Access 和 MYSQL 数据类型比较

PHP 准备的 postgres 查询失败,返回 :"could not determine data type of parameter $1"

database - 将 Magento 站点从 Localhost 迁移到 Live。获取和错误

mysql - 如何获取mysql中同一张表的计数值为零?

python - (Python) MySQL 数据库身份验证问题

sql - 如何确定Oracle ORA_Hash函数的最佳Max_bucket和Seed_value?