我的Postgres版本是9.6
我今天尝试使用此命令从我的数据库中删除索引:
drop index index_name;
它引起了很多锁定 - 整个应用程序都被卡住了,直到我杀死掉落的所有会话(为什么它被分成几个会话?)。
当我检查锁时,我看到几乎所有被阻止的会话都执行该查询:
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
FROM
pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = <index_able_name>::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum;
这是否会阻止系统操作?
所以我决定使用concurrently选项删除索引以防止锁定。
drop index concurrently index_name;
我现在从PGAdmin执行它(因为你无法从noraml事务中运行它。)
它跑了20分钟并没有完成。索引大小为20MB + - 。
当我检查数据库中的锁时,我发现该表上有一个选择查询,并阻止了drop命令。
但是当我把这个选择并在另一个会话中执行时 - 这变化很快(2-3)秒。
那为什么会阻止我的摔倒呢?还有其他选择吗?也许要禁用索引?
答案 0 :(得分:2)
drop index
和drop index concurrently
通常是非常快的命令,但它们都像所有DDL命令一样,需要对表进行独占访问。
他们的不同之处仅在于他们如何尝试实现此独占访问权限。普通drop index
只会请求对表进行独占锁定。这将阻止在drop
查询开始后尝试使用该表的所有查询(甚至选择)。它将执行此操作,直到它将获得独占锁定 - 当所有以任何方式触及表的事务(在drop命令之前启动)完成并且提交drop
的事务时。这解释了您的应用程序停止工作的原因。
concurrently
版本还需要简短的独占访问权限。但它的工作方式不同 - 它不会阻止表,但要等到没有其他查询触及它然后执行(通常是简短的)工作。但如果桌子经常忙碌,它将永远不会找到这样的时刻,并无限期地等待它。另外我想它只是尝试每隔X毫秒重复锁定一次表,直到成功为止,因此稍后的并行执行可以更加幸运并且完成得更快。
如果您看到多个同时会话尝试删除索引,并且您不希望这样,那么您的应用程序中就会出现错误。数据库永远不会自行完成。