这是用例:
我有一张桌子,上面有一堆可用或不可用的唯一代码。作为事务的一部分,我想从表中选择一个可用的代码,然后稍后在事务中更新该行。由于这可能同时发生在许多会话中,我希望理想地选择一个随机记录并在表上使用行级锁定,这样其他事务就不会被从中选择行的查询阻塞桌子。
我使用 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:我选择的最终解决方案
鉴于 rand() 在 MySQL 中存在一些问题,我选择的策略是:
我选择 50 个代码 id,其中可用 = 1,然后我在应用程序层中对数组进行洗牌,以向顺序添加一定程度的随机性。
从可用的 tbl_codes 中选择 id = 1 限制 50
我开始循环从我的洗牌数组中弹出代码,直到我能够选择一个带锁的代码
select * from tbl_codes where available = 1 and id = :id