据我了解,我们的查询正在等待锁的事实意味着它一直在等待锁,并且它从未更改过任何内容。
正确-如果您看到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
麻烦。)