【发布时间】:2012-09-26 03:33:13
【问题描述】:
我在 MySQL 中使用行锁定(事务)来创建作业队列。使用的引擎是 InnoDB。
SQL 查询
START TRANSACTION;
SELECT *
FROM mytable
WHERE status IS NULL
ORDER BY timestamp DESC LIMIT 1
FOR UPDATE;
UPDATE mytable SET status = 1;
COMMIT;
据此webpage,
The problem with SELECT FOR UPDATE is that it usually creates a single synchronization point for all of the worker processes, and you see a lot of processes waiting for the locks to be released with COMMIT.
问题:这是否意味着在执行第一个查询时,需要一些时间才能完成之前的事务,当第二个类似查询发生在第一个事务提交之前,它必须在执行查询之前等待它完成?如果这是真的,那么我不明白为什么单行的行锁定(我假设)会影响下一个不需要读取该锁定行的事务查询?
此外,是否可以通过执行UPDATE 而不是事务来解决此问题(并且仍然实现行锁定对作业队列的效果)?
UPDATE mytable SET status = 1
WHERE status IS NULL
ORDER BY timestamp DESC
LIMIT 1
【问题讨论】:
-
锁定是基于存储引擎的——你用的是什么?
-
谢谢(还有 9 个字符)
-
不幸的是,您的
status IS NULL ORDER BY查询保证了对mytable.的全表扫描 索引对于 IS NULL 搜索没有帮助。如果您可以重构代码以消除 NULL 状态值、搜索其他值并为此使用索引,您将节省大量的表扫描时间。 -
将
status的默认值设置为0并对其进行索引会更好吗? -
是的,该方案将使您的“查找下一个符合处理条件的 mytable 行”操作更快。