我创建一个表空间
create tablespace test_tablespace location '/path/to/tablespace/dir';
接下来,我创建一个表并填充数据
create table test_table (id numeric, file_name varchar) tablespace test_tablespace;
insert into test_table (id, file_name) values (1,'test_field1'),(2,'test_field2'),(3,'test_field3');
之后,我创建一个使用 dblink 删除表和表空间的函数并运行它:
CREATE OR REPLACE FUNCTION test_func(par_tablespace_name varchar)
RETURNS void
LANGUAGE 'plpgsql'
AS $BODY$
begin
perform dblink_connect_u('port=5432 user=postgres dbname=test_db');
perform dblink_exec('drop table test_table');
perform dblink_exec('drop tablespace '|| par_tablespace_name );
perform dblink_disconnect();
end;
$BODY$;
select test_func('test_tablespace');
这会导致僵局。
在 pg_stat_activity 中:
pid | 等待事件类型 | 等待事件 | 查询 |
---|---|---|---|
609024 | 空 | 空 | 选择 test_func('test_tablespace'); |
610910 | IPC | ProcSignalBarrier | 删除表空间test_tablespace |
pg_blocking_pids(610910)为空
在 postgres 日志中:
[610910] 语句:删除表空间 test_tablespace [610910] 日志:仍在等待 PID 609024 的后端接受 ProcSignalBarrier
在 PostgreSQL 13 中它运行良好。如果表空间为空(没有数据文件),那么它运行不会出现问题。 为什么会发生这种情况以及如何通过另一个会话中的函数删除表空间?
这可能是由 commit 4eb2176318d 引起的,如评论中所述。
DROP TABLESPACE
正在等待执行 dblink_exec()
调用的会话的确认,但在函数调用完成之前不会发送确认。如果您从不同的集群连接 dblink,您能否确认该操作是否有效?
您可能必须想出不同的做事方式。如果你说表空间为空就没有问题,也许你可以关闭删除表和删除表空间之间的dblink连接。