Postgresql 加入“安全吗?”;pg“U锁”;生产代码中的表?

Postgresql 加入“安全吗?”;pg“U锁”;生产代码中的表?,postgresql,concurrency,locking,Postgresql,Concurrency,Locking,我有一个类似于tablet1的队列,保存时间戳排序的数据。其中一列是外键ext\u id。我有许多工人处理t1中的行,并在工作完成后删除它们。该过程的结果是将行向上插入到另一个表t2t2也引用了ext\u id,但在这种情况下,关系是唯一的:如果指向特定ext\u id的行已经存在,我想更新它,而不是插入它 只要一个工人在处理数据,任务就相当简单。当多个辅助线程参与工作时,SKIP LOCKED子句起到了解救作用:每个线程都锁定它正在处理的行,并使它对其他线程不可见SKIP LOCKED子句保证

我有一个类似于table
t1
的队列,保存时间戳排序的数据。其中一列是外键
ext\u id
。我有许多工人处理
t1
中的行,并在工作完成后删除它们。该过程的结果是将行向上插入到另一个表
t2
t2
也引用了
ext\u id
,但在这种情况下,关系是唯一的:如果指向特定
ext\u id
的行已经存在,我想更新它,而不是插入它

只要一个工人在处理数据,任务就相当简单。当多个辅助线程参与工作时,
SKIP LOCKED
子句起到了解救作用:每个线程都锁定它正在处理的行,并使它对其他线程不可见
SKIP LOCKED
子句保证线程不会在源表
t1
方面相互干扰。问题是,他们仍然可以尝试同时将行插入表
t2
。由于
t2
上存在唯一性约束,如果多个工作人员选择
t1
行共享
ext\u id
,则会产生错误。由于约束引发错误,我可以简单地重试处理特定行,但这样我就失去了处理顺序的保证(更不用说基于异常的流控制感觉像是严重的反模式)

我考虑添加辅助的“同步”表(我们称之为
sync
),它将保存当前正在处理的每个
ext\u id
的条目。处理变得更加复杂:在实际开始处理之前,我需要提交
sync
行插入,以便其他线程可以使用此信息选择可以安全处理的
t1
t1
行选择可以加入辅助表,并匹配
ext_id
不在
sync
表中的第一行。并发线程仍有可能选择连续的行并尝试插入指向相同
ext\u id
的同步行。如果发生这种情况,我需要重试
t1
行选择

第二种方法解决冲突的
t1
行的并发处理,并保证行顺序得到维护(在
ext\u id
值定义的分区内)。它未能解决的是基于失败插入的脏流控制结构

PostgreSQL提供了建议锁机制,允许构建特定于应用程序的自定义同步逻辑

引自:

例如,咨询锁的一个常见用途是模拟所谓的“平面文件”数据管理系统典型的悲观锁定策略。虽然存储在表中的标志可以用于相同的目的,但建议锁更快,避免表膨胀,并且在会话结束时由服务器自动清除

使用顾问锁正好解决了这个问题,根据文档,应该可以产生更好的性能。当一个进程选择一行时,它还将获得用
ext\u id
参数化的通知锁。如果另一个进程试图选择冲突的行,它将不得不等待另一个锁被释放

这要好得多,但在某些情况下,它将禁止工作人员子集同时执行其任务,并使他们按顺序等待执行任务。这些工作人员可以做的,而不是等待,是尝试获取另一行:一些基于
sync
的解决方案,通过使用外部联接排除
t1
行来解决

经过长时间的介绍,最后,问题是:

通过查询
pg_锁
view,可以检查现有的咨询锁。此视图可以作为查询中的常规关系联接。在获取下一个
t1
行时加入它,以排除由于现有锁而当前无法处理的行。由于
pg_locks
不是常规表,我怀疑这种方法是否安全

是吗