Postgresql 锁定当前插入的行,以避免读取时出现争用情况

Postgresql 锁定当前插入的行,以避免读取时出现争用情况,postgresql,transactions,locking,Postgresql,Transactions,Locking,我有一个系统,在将行插入数据库时,我会将事件作为事务的一部分进行分派 这是为了确保只有成功插入时才会调度事件,并且在事件调度失败时回滚插入 问题是,在成功插入后调度事件时,我看到了一个竞赛条件。有时,在提交事务之前,相应的事件侦听器将接收事件,这将导致此时该行不可用 我想要实现的是,在插入行A时,任何试图读取行A的进程都必须等到提交了行A的事务之后 这是一个合理的方法吗?如何最好地实现 对于两个进程A和B 它当前的工作方式 启动事务 插入的尝试 调度事件 B接收事件并尝试读取插入的行 B由于记录

我有一个系统,在将行插入数据库时,我会将事件作为事务的一部分进行分派

这是为了确保只有成功插入时才会调度事件,并且在事件调度失败时回滚插入

问题是,在成功插入后调度事件时,我看到了一个竞赛条件。有时,在提交事务之前,相应的事件侦听器将接收事件,这将导致此时该行不可用

我想要实现的是,在插入行A时,任何试图读取行A的进程都必须等到提交了行A的事务之后

这是一个合理的方法吗?如何最好地实现

对于两个进程AB

它当前的工作方式

  • 启动事务
  • 插入的尝试
  • 调度事件
  • B接收事件并尝试读取插入的行
  • B由于记录尚不可见,引发异常
  • 提交事务
  • 我希望它如何工作

  • 启动事务
  • 插入的尝试
  • 调度事件
  • B接收事件并尝试读取插入的行
  • B该行当前被事务锁定,因此它将等待释放
  • 提交事务
  • B锁被释放,新插入的行被返回
  • 根据问题和评论,我认为这里的主要问题是希望“A”根据未提交行的内容发送事件,并且希望“B”读取该未提交行并对其执行操作。但在关系理论和SQL数据库中,您不知道提交是否会成功。提交失败的原因有很多——不仅因为某些约束失败,还因为权限或磁盘空间不足等原因

    为了从您的评论中借用词语,dbms管理数据库从一个一致状态到另一个一致状态的转换。未提交的行不属于一致数据库状态的一部分。只有成功提交的行是一致数据库状态的一部分

    所以我认为,一般来说,在“B”尝试读取新行之前,您需要“A”进行提交。我认为这是正确的,即使您切换到支持“readuncommitted”事务隔离级别的dbms。(PostgreSQL没有,至少不是你想象的那样。)

    这意味着如果“分派”失败,“B”将负责删除新行(或通知“A”删除它)。“A”和“B”都不能回滚已提交的事务


    对于另一个过程“C”,监督“A”和“B”的行动可能更有意义

    你的描述令人困惑。一方面,您说事件只会“为了成功插入”而被调度。另一方面,您说当分派失败时,将回滚插入。但通常对成功插入的理解意味着事务已提交。无法回滚已提交的事务。编辑您的问题,并澄清事件的实际顺序。在诸如PostgreSQL之类的SQL数据库中,任何试图读取A行的进程都必须等到A行的事务提交之后,这与此有关。PostgreSQL默认使用“读取提交”隔离,但这是每个事务的设置——每个事务都可以选择不同的隔离级别。对此表示抱歉。我已经添加了一些例子,希望在阅读您的编辑后能够澄清。“a”是否有令人信服的理由在“a”提交之前发送事件?这对我来说没有意义。提交失败的原因有很多。提交,然后分派似乎更有意义。您的设计需要一个不一致的状态开始。您希望调度依赖于未提交行的事件。未提交行=此处的状态不一致。