postgresql 如何释放可能的Postgres行锁?

fwzugrvs  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(6)|浏览(257)

我通过phpPgAdmin接口在一个大型PostgreSQL表上运行update语句。由于运行时间过长,此操作超时。
我现在可以更新该表中的一些行,但不是全部。尝试更新某些行将挂起。
行是否锁定?如何允许更新这些行?

yquaqz18

yquaqz181#

可以看到锁。
这里有一个视图,它比直接使用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%');

其他解决方案:http://wiki.postgresql.org/wiki/Lock_Monitoring

5jdjgkvh

5jdjgkvh2#

简单:

Get the active locks from 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;

Copy the pid(ex: 14210) from above result and substitute in the below command.

SELECT pg_terminate_backend(14210)
dz6r00yl

dz6r00yl3#

要从Postgres释放可能的锁,我通常按顺序执行这些操作。
1.通过运行以下查询,在数据库中查找长时间运行的查询。这将帮助您获取阻塞更新的长时间运行的查询的PID。

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';

1.或者通过运行此查询,您是否可以找出哪些进程持有特定表上的锁

SELECT *
FROM pg_locks l
JOIN pg_class t ON l.relation = t.oid AND t.relkind = 'r'
WHERE t.relname = 'Bill';

1.一旦你找出PID是'活动'和阻止您的更新,您可以杀死它运行这个查询。这需要一些时间来杀死这个过程。

SELECT pg_cancel_backend(__pid__);

1.通过运行查询2检查进程是否被杀死。如果该进程仍然处于活动状态,则通过运行此查询终止该进程。

SELECT pg_terminate_backend(__pid__);
j7dteeu8

j7dteeu84#

你运行的是哪个版本的PostgreSQL?下面的假设是8.1.8或更高版本(它可能也适用于早期版本,我不知道)。
我假设你的意思是phpPgAdmin超时了--PostgreSQL后端将花费与完成查询/更新所需的时间一样长。在这种情况下,可能原始会话仍然处于活动状态,UPDATE查询仍然在运行。我建议在托管PostgreSQL服务器进程的机器上运行以下查询(取自chapter 24 of the PostgreSQL docs),以查看会话是否仍然活跃:

ps auxwww|grep ^postgres

应显示几行:postmaster主进程为1,“writer”、“stats buffer”和“stats collector”进程各为1。所有剩余的行都用于服务DB连接的进程。这些行将包含用户名和数据库名。
希望您可以从中看到执行原始UPDATE的会话是否仍然存在。虽然理论上你可以通过SELECT从系统视图pg_stat_activity找到更详细的信息,默认情况下PostgreSQL不会设置为填充最有用的字段(例如current_queryquery_start)。请参阅第24章了解将来如何启用此功能。
如果您看到会话仍然存在,请将其关闭。您需要以运行进程的用户(通常是postgres)或root用户的身份登录才能登录--如果您自己不运行服务器,请让DBA为您完成此操作。
还有一件事为了更新表中的行,PostgreSQL避免使用锁。相反,它允许每个写入事务创建DB的新“版本”,当事务提交时,该版本将成为“当前版本”,前提是它不与其他事务同时进行的更新冲突。所以我怀疑你所看到的“绞刑”是由其他原因引起的--尽管我不确定是什么原因。(你有没有检查过一些明显的事情,比如包含数据库的磁盘分区是否已满?)

h9vpoimq

h9vpoimq5#

这将清除所有表上的所有锁。

SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE pid <> pg_backend_pid();
qncylg1j

qncylg1j6#

我从来没有使用过PostreSql,但如果它和其他类似,我会说你必须杀死连接/结束持有锁的事务。

相关问题