SQL大师!
我的postgres 15数据库在SERIALIZABLE
隔离级别下运行,我偶尔会看到带有奇怪错误消息的serialization_failure (40001)
错误:
DETAIL: Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction 39594340.
字符串
对于这类错误,我们限制了自动重试,但在最近的一个案例中,在一个多小时内,没有任何东西可以触及受影响的表--任何UPDATE
尝试都会失败,并出现相同的错误。
对我来说奇怪的是,这个错误引用了txn 39594340
,它在错误消息开始出现在我们的日志中之前成功提交了15分钟。
这个错误的特殊变体在Google上并没有产生太大的影响。也许最相关的是https://www.mail-archive.com/[email protected]/msg156458.html,它讨论了耗尽共享内存的 predicate 锁(或达到max_pred_locks_per_transaction
限制的txns)如何失去很多粒度,特别是如果它们交换到磁盘(甚至DB也可能丢失!?!?)
无论如何,在我们的例子中,似乎我们有一个非常复杂的,长时间运行的txn(称之为txnA
),几乎肯定会达到默认的max_pred_locks_per_transaction=64
限制。然后我们有其他简单得多的txn,基本上只执行1-2个UPDATE
语句(txnB
)。
committed txn(old committed transaction 39594340
)和failing-with-serialization-error txn都是简单的txnB
类型,但可能与txnA
并发发生。同时,txnA
与txnB
没有接触相同的表,但在两者之前启动,并且在我们开始看到错误时仍然运行。
看起来可能有一些错综复杂的依赖关系,与长期运行的txn的 predicate 锁中的特定性丢失有关。这个假设疯了吗?
否则一个 * 已提交的 * txn如何影响当前的txn?
TIA在这里的任何见解!
1条答案
按热度按时间kd3sttzy1#
很难说到底发生了什么,但是在
SERIALIZABLE
隔离级别上获取的 predicate 锁会一直保留到最后一个并发事务结束,所以肯定涉及到一个长时间运行的事务。