死锁报错1
UPDATE deadlock_example SET value = value + 1 WHERE id = 1
ERROR: deadlock detected
DETAIL: Process 95 waits for ShareLock on transaction 3553457; blocked by process 187.
Process 187 waits for ShareLock on transaction 3553458; blocked by process 95.
HINT: See server log for query details.
CONTEXT: while updating tuple (0,6) in relation “deadlock_example”
其中 Process 95 在等待共享锁(ShareLock)的事务 3553457,而 Process 187 在等待共享锁的事务 3553458。这两个事务相互阻塞,形成了死锁。
具体解释如下:
Process 95 正在等待事务号为 3553457 的共享锁,但被 Process 187 阻塞。
Process 187 正在等待事务号为 3553458 的共享锁,但被 Process 95 阻塞。
这种相互等待的情况导致了死锁。在这种情况下,PostgreSQL 选择其中一个事务(在这里是 Process 95)作为死锁牺牲者,回滚该事务以解除死锁。
死锁报错2
UPDATE deadlock_example SET value = value + 1 WHERE id = 1
ERROR: current transaction is aborted, commands ignored until end of transaction block
这个错误消息表明在事务中发生了一个错误,导致整个事务被中止。在 PostgreSQL 中,一旦事务发生错误,该事务就会被中止,后续的命令将被忽略,直到事务块结束。
查看数据库表信息:
SELECT pid, datname, usename, query, state
FROM pg_stat_activity
state
为idle in transaction (aborted)
,表示连接处于事务中空闲状态,并且事务已中止(aborted)。
这种状态通常表示连接在事务中执行了某些操作,但由于某些原因,该事务已经中止。在这个特定的情况下,连接正在执行一个 UPDATE
查询,但由于死锁等原因,事务中止了。
解决办法
使用 PostgreSQL 中的 pg_terminate_backend 函数可以终止指定的连接。
在 pg_stat_activity 表中查找要终止的连接的进程ID (pid)。在我的情况中,pid 为 95 的连接发生了死锁,所以你可以选择终止该连接。
执行如下命令:
SELECT pg_terminate_backend(95);
返回结果为 t
,表示执行成功。
SELECT pg_terminate_backend(187);
再次查看pg_stat_activity信息,pid为95的进程已经不见了
。
再次执行刚才报错的sql,发现可以成功执行了。