首页 > 解决方案 > 我可以获得一个 postgresql 锁来防止对表的一部分进行并发插入吗?

问题描述

我有一个连接表attendees和一个额外的列roomsusers表示随机分配的字符串(来自字符串池)。

我想防止两个用户同时输入意外被分配相同的字符串- 所以我希望用户 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"

标签: postgresqllocking

解决方案


在 SO 上令人沮丧的几天后,我最终在 Reddit 上得到了一个有用的回复,解决了这个问题:

在房间表上使用SELECT FOR UPDATE查询,锁定与房间对应的行,直到第一个用户的事务完成。


推荐阅读