取消等待锁定的PostgreSQL ALTER TABLE查询是否安全?


10

我们在ALTER TABLE几个小时前开始查询,直到最近(通过pg_stat_activity)才意识到它正在等待锁。我们发现了另一个查询,该查询在我们要更改的表上拥有一个锁,并且不让它走。

我们的查询是一个“简单”查询(更改列数据类型),但是它在大型表上运行。

我们决定杀死而不是杀死保持锁定状态的进程,而不是杀死ALTER TABLE

我们并没有包裹ALTER TABLE在一个事务中。

据我了解,我们的查询正在等待锁的事实意味着它一直在等待锁,并且从未更改过任何内容。

这是真的?我们完全取消ALTER TABLE查询是否安全?还是查询已经修改了某些内容并取消它会使我们的数据库处于某种中间状态?

PS:计划使用取消它SELECT pg_cancel_backend(pid);。如果这是个坏主意,请告诉我。


1
取消ALTER TABLE应该没问题。PostgreSQL有事务性的DDL,您应该处于完全没有运行ALTER TABLE的状态。
Josh Kupershmidt 2015年

因此,当您说PostgreSQL具有事务DDL时,是否意味着任何模式更改查询实际上都在事务内部运行?
JMTyler

1
在您的情况下,ALTER TABLE是“基本上在事务内运行的”,因为您说过“我们没有在事务中包装ALTER TABLE。” 如果愿意,可以写BEGIN; ALTER TABLE foo ...; ALTER TABLE栏...; 等 承诺; -这是PostgreSQL具有事务性DDL的真正杀手级功能。但是对于您当前的情况,是的,可以安全地取消ALTER TABLE并自动回滚,就像从未发生过一样。
Josh Kupershmidt,2015年

非常感谢您的快速回复!这是非常好的信息。您能否将其发布为答案,以便我将其标记为已接受?
JMTyler

Answers:


13

据我了解,我们的查询正在等待锁的事实意味着它一直在等待锁,并且它从未更改过任何内容。

正确-如果您看到ALTER TABLE的pg_stat_activity.waiting是“ true”,那几乎可以肯定意味着它正在耐心地等待其目标表上的ACCESS EXCLUSIVE锁及其实际工作(必要时重写表,更改目录) ,重建索引等)还没有开始。

对我们来说,完全取消ALTER TABLE查询是否安全?还是查询已经修改了某些内容并取消它会使我们的数据库处于某种中间状态?

在PostgreSQL中取消查询(或等效地回滚事务)没有任何其他数据库可能已经吓到的数据库损坏危险(例如,本页底部的可怕警告)。这就是为什么非超级用户在最新版本中可以自由使用pg_cancel_backend()pg_terminate_backend()杀死在其他后端运行的自己的查询-他们可以安全使用,而不必担心数据库损坏。毕竟,PostgreSQL必须准备好处理任何被杀死的进程,例如,OOM杀手的SIGKILL,服务器关闭等。这就是WAL日志的目的。

您可能还已经看到,在PostgreSQL中,可以执行嵌套在(多语句)事务中的大多数DDL命令,例如

BEGIN;
ALTER TABLE foo ...;
ALTER TABLE bar ...;
-- more stuff
COMMIT; -- or ROLLBACK; if you've changed your mind

(对于确保模式迁移完全或完全不进行都是很棒的。)您说过:

我们并没有包裹ALTER TABLE在一个事务中。

单个命令就可以了-从文档中

PostgreSQL实际上将每个SQL语句都视为在事务内执行。如果不发出BEGIN命令,则每个单独的语句都有一个隐式的BEGIN和(如果成功的话)用COMMIT包裹起来。由BEGIN和COMMIT包围的一组语句有时称为事务块。

因此ALTER TABLE,通过pg_cancel_backend()控制psql提示符发出的Ctrl-C或Ctrl-C 取消该命令,将产生与您完成操作类似的效果

BEGIN;
ALTER TABLE ... ;
ROLLBACK;

(尽管您希望看到,但是即使您打算这样做,取消昂贵的操作ALTER TABLE也可以避免数据库不必要的ROLLBACK麻烦。)


5

要详细说明Josh的正确答案:

对我们来说,完全取消ALTER TABLE查询是否安全?

是。

即使在重写表的过程中也很安全。

如果您愿意,可以关闭整个PostgreSQL服务器,或者实际上是关闭运行它的机器,然后重新启动它,一切都会好起来的。PostgreSQL中的DDL具有事务性和崩溃安全性。

DDL操作通过WAL记录,并确保它们可以回滚或崩溃或中止后在恢复后完成。


3
只是关于“您可以关闭整个PostgreSQL服务器,或者实际上是在其上运行的计算机,重新启动它,然后一切都会好起来的”的注释-只要您拥有可靠的硬件且不依赖于fsync,这是正确的,wiki.postgresql.org/wiki/Reliable_Writes
Josh Kupershmidt

2
@JoshKupershmidt当然可以,但这并不特定于DDL。如果你有不同步的问题,那么你很崩溃不安全的一切
Craig Ringer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.