这是一个使用案例:
我有一张表格,其中包含一堆状态为“可用”或“不可用”的唯一代码。作为交易的一部分,我想从表格中选择一个可用的代码,然后稍后在交易中更新该行。由于这可能会同时发生在许多会话中,我希望最好随机选择一条记录,并在表格上使用行级锁定,以便其他事务不会被查询阻止。
我正在使用InnoDB作为存储引擎,我的查询大致如下:
然而,与其仅锁定表中的一行,它最终锁定整个表。有没有人能给我一些指导,如何使此查询不锁定整个表而仅锁定行? 更新 补充说明:通过在我的选择中指定显式键而不是执行rand(),我能够实现行级锁定。当我的查询看起来像这样时:
我有一张表格,其中包含一堆状态为“可用”或“不可用”的唯一代码。作为交易的一部分,我想从表格中选择一个可用的代码,然后稍后在交易中更新该行。由于这可能会同时发生在许多会话中,我希望最好随机选择一条记录,并在表格上使用行级锁定,以便其他事务不会被查询阻止。
我正在使用InnoDB作为存储引擎,我的查询大致如下:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
然而,与其仅锁定表中的一行,它最终锁定整个表。有没有人能给我一些指导,如何使此查询不锁定整个表而仅锁定行? 更新 补充说明:通过在我的选择中指定显式键而不是执行rand(),我能够实现行级锁定。当我的查询看起来像这样时:
select * from tbl_codes where available = 1 and id=5 limit 1 for update
查询2:
select * from tbl_codes where available = 1 and id=10 limit 1 for update
然而,这并不能真正帮助解决问题。
附录2:我采用的最终解决方案
考虑到MySQL中rand()存在一些问题,我选择的策略是:
我选择50个可用状态码id,然后在应用程序层对数组进行洗牌,以增加顺序的随机性。
select id from tbl_codes where available = 1 limit 50
我开始在循环中从我的洗牌数组中弹出代码,直到我能够选择一个带锁定的代码为止。
select * from tbl_codes where available = 1 and id = :id
select id from tbl_codes where available = 1 LIMIT :offset, 50
当您有许多代码可供选择时,这种方法效果很好。 - Jay