我通过phpPgAdmin界面在一个大的PostgreSQL表上运行了一条更新语句。由于运行时间过长,这个操作超时了。
现在我可以更新该表中的一些行,但不是全部。尝试更新某些行会导致卡住。
这些行被锁定了吗?如何允许更新这些行?
我通过phpPgAdmin界面在一个大的PostgreSQL表上运行了一条更新语句。由于运行时间过长,这个操作超时了。
现在我可以更新该表中的一些行,但不是全部。尝试更新某些行会导致卡住。
这些行被锁定了吗?如何允许更新这些行?
可以查看锁定情况。
这里提供了一种比直接使用pg_locks更简单的视图:
CREATE OR REPLACE VIEW public.active_locks AS
SELECT t.schemaname,
t.relname,
l.locktype,
l.page,
l.virtualtransaction,
l.pid,
l.mode,
l.granted
FROM pg_locks l
JOIN pg_stat_all_tables t ON l.relation = t.relid
WHERE t.schemaname <> 'pg_toast'::name AND t.schemaname <> 'pg_catalog'::name
ORDER BY t.schemaname, t.relname;
SELECT * FROM active_locks;
并通过以下方式终止它:
SELECT pg_cancel_backend('%pid%');
简单易懂:
从pg_locks获取活动锁:
SELECT t.relname, l.locktype, page, virtualtransaction, pid, mode, granted
FROM pg_locks l, pg_stat_all_tables t
WHERE l.relation = t.relid
ORDER BY relation asc;
从上面的结果中复制pid(例如:14210),并将其替换为下面的命令。
SELECT pg_terminate_backend(14210)
Find long-running queries in your DB by running the following query. This will help you fetch the PIDs of the long-running query which is blocking your update.
SELECT
pid,
now() - pg_stat_activity.query_start AS duration,
query,
state
FROM pg_stat_activity
WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes';
or if you can find out which processes are holding a lock on a particular table by running this query
SELECT *
FROM pg_locks l
JOIN pg_class t ON l.relation = t.oid AND t.relkind = 'r'
WHERE t.relname = 'Bill';
Once you figure out the PID which is 'active' and blocking your update you can kill it by running this query. It takes some time to kill the process.
SELECT pg_cancel_backend(__pid__);
Check by running Query 2 if the process is killed. If it still is active then kill this process by running this query.
SELECT pg_terminate_backend(__pid__);
你正在运行哪个版本的PostgreSQL?以下假设你运行的是8.1.8或更新版本(它可能也适用于早期版本,但我不确定)。
我猜你指的是phpPgAdmin超时了——PostgreSQL后端将花费足够的时间来完成一个查询/更新。在这种情况下,原始会话可能仍然存在,而UPDATE查询仍在运行。建议在托管PostgreSQL服务器进程的机器上运行以下查询(摘自PostgreSQL文档的第24章),查看会话是否仍然存在:
ps auxwww|grep ^postgres
会显示几行: 一个是 postmaster
主进程,还有一个是 "writer"、"stats buffer" 和 "stats collector" 进程。任何剩余的行都是为服务于数据库连接的进程所用,这些行将包含用户名和数据库名称。
希望从中可以看出您执行原始 UPDATE 的会话是否仍然存在。虽然理论上您可以通过从系统视图 pg_stat_activity
中进行 SELECT
来查找更详细的信息,但默认情况下 PostgreSQL 并未设置以填充最有用的字段(如 current_query
和 query_start
)。请参阅第 24 章以了解如何在将来启用此功能。
如果您看到会话仍然存在,请终止它。您需要以运行该进程的用户身份(通常是 postgres
)或 root 登录才能这样做 - 如果您自己不运行服务器,请让您的 DBA 为您执行此操作。
还有一件事:对于更新表中的行,PostgreSQL 避免使用锁定。相反,它允许每个写事务创建数据库的新“版本”,当事务提交时,该版本成为“当前版本”,前提是它不与其他事务同时进行的更新发生冲突。因此,我怀疑您看到的“挂起”是由其他原因引起的 - 尽管是什么原因,我不确定。(您是否检查了一些显而易见的事情,例如包含数据库的磁盘分区是否已满?)
postgres 15398 ... idle in transaction
或其他类似的内容,并在 Putty 中键入 kill 15398
。 - NoumenonSELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE pid <> pg_backend_pid();
请在生产数据库上谨慎使用。
我从未使用过PostreSql,但如果它与其他数据库类似,我会建议您终止持有锁的连接/事务。
active_locks
的视图或表。您是不是指的是pg_locks
? - user330315