mysql - 为选择查询锁定行?

标签 mysql

我有一个包含唯一产品 ID 列表的 mysql 表(表 A)。使用此表的应用程序使用多个线程,每个线程选择一个表行(最上面),使用 API 获取产品数据并将其更新到不同的表(表 B)。完成后,线程删除表 A 中相应的产品 ID 行,并选择另一个进行处理(循环直到表 A 中的所有行都已删除,而表 B 已更新)。

如何防止我的应用程序的线程意外地处理表 A 的同一行?有没有办法锁定一行不被选中?

例子: 应用程序的线程 1 从表 A 中选择行 1。从 API 抓取所有相关数据并将其更新到表 B 大约需要 10 到 15 秒。发生这种情况时,线程 2 将启动并检查表 A 以选择要处理的行。在这种情况下,我只想锁定第 1 行,这样线程 2 就不会看不到/读取它,而是选择第 2 行。

最佳答案

native MySQL 锁定不提供此功能。您可以使用列来执行您的“锁定”。

假设每个线程都有一个唯一的 ID,您可以创建一个名为 thread_owner 的列,默认值为 0。

一个线程会像这样抓取一行:

UPDATE mytable
SET thread_owner = :my_threadID
WHERE thread_owner = 0
LIMIT 1

然后像这样选择行(它可能返回 none,如果没有要处理的行):

SELECT *
FROM mytable
WHERE thread_owner = :my_threadID

然后处理,最后删除。

此解决方案适用于 MyISAM 和 InnoDB。

但是,对于 InnoDB,它可能会很慢,因为每个 UPDATE 语句都试图锁定所有 thread_owner = 0 的行,除非您确定每次都以相同的顺序锁定所有行,否则它甚至可能导致一个僵局。因此,您可以尝试在 UPDATE 语句中显式锁定整个表:

LOCK TABLES mytable WRITE;
UPDATE mytable
SET thread_owner = :my_threadID
WHERE thread_owner = 0
LIMIT 1;
UNLOCK TABLES;

这样,MyISAM 和 InnoDB 将以相同的方式工作。

关于mysql - 为选择查询锁定行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11157488/

相关文章:

java - 无法使用hibernate连接到mysql

php - Laravel 获取按关系表排序的集合

mysql - 我怎样才能使这个 MySQL 查询(带有子查询)更快?

mysql - 如何找到最宽的租金价格区间?

php - 无法编辑与 CakePHP 的 HABTM 关联中的属性

python - mysql.connector - 你的 SQL 语法有错误;第 1 行 '%s' 附近

php - 防止不相关的mysql数据

mysql - 错误 1030 (HY000) 在第 25 行 : Got error 168 from storage engine

使用 .frm 文件和 ibdata 文件恢复 MySQL InnoDB 数据库

mysql - 如何使用分配给变量的找到的行数并在 INSERT 语句中使用它?