postgresql - 我可以获得一个 postgresql 锁来防止对表的一部分进行并发插入吗?
问题描述
我有一个连接表attendees
和一个额外的列rooms
,users
表示随机分配的字符串(来自字符串池)。
我想防止两个用户同时输入意外被分配相同的字符串- 所以我希望用户 B 等待查找房间中的先前用户(及其分配的字符串),直到用户 A 完成插入- 但我不想做一个表锁,因为 say 的行插入room_id = 12
不会影响room_id = 77
.
我不能使用唯一约束来解决这个问题,因为在单个房间中有大量用户的情况下可能会出现重复的字符串(一旦所有字符串都被使用过一次,字符串就会被均匀地重新分配)。*
我的猜测是在做类似的事情
SELECT room_id, user_id, random_string WHERE room_id = ? FOR UPDATE
不会有帮助,因为它不会阻止用户 B 进行插入 - 即使这SELECT FOR UPDATE
阻止了用户 B 执行相同的调用来读取与该房间对应的行,如果用户 A 和用户 B 都会发生什么是第一个加入的(并且没有任何行room_id
可以锁定)?
我会使用钥匙在 上的咨询锁room_id
吗?如果我有多个并发写入(例如,用户 A 应该先完成,然后是用户 B,然后是用户 C),这仍然会有所帮助吗?
*这里是字符串不一定唯一的示例:假设字符串池是"red", "blue", "green"
——前三个进入的用户随机分配一个,然后池重置。接下来的三个用户也是随机分配的,所以对于房间里的六个用户,正好两个会有"red"
、两个"blue"
和两个"green"
。
解决方案
在 SO 上令人沮丧的几天后,我最终在 Reddit 上得到了一个有用的回复,解决了这个问题:
在房间表上使用SELECT FOR UPDATE
查询,锁定与房间对应的行,直到第一个用户的事务完成。
推荐阅读
- python - 熊猫组合数据框中的重复项
- java - 如何将优先级升级到 log4j-2?
- react-native - 关于 mapDispatchToProps 的困惑
- python - Selenium 无法获取选择结果
- maven - Maven:如何不依赖父 POM
- c++ - 创建单个线程时 SteamVR 帧峰值
- reactjs - 映射数据的问题 - React
- teradata - 如何在 teradata 中通过 select 语句放置新行?
- javascript - 有没有办法将变量附加到类 javascript
- python - Confusing python variable scope