执行SQL时出现表死锁,提示LOCK_WAIT_TIMEOUT锁等待超时
问题现象
执行SQL时出现LOCK_WAIT_TIMEOUT锁等待超时的错误。
原因分析
锁等待超时一般是因为有其他的SQL语句已经持有了锁,当前SQL语句需要等待持有锁的SQL语句执行完毕释放锁之后才能执行。当申请的锁等待时间超过GUC参数lockwait_timeout的设定值时,系统会报LOCK_WAIT_TIMEOUT的错误。
处理方法
- 8.1.x及以上集群版本,通过pgxc_lock_conflicts视图查看锁冲突情况。
1
SELECT * FROM pgxc_lock_conflicts;
8.0.x及之前集群版本,执行以下SQL查询查看是否有阻塞的SQL语句。1 2 3 4 5 6 7 8 9 10 11
SELECT w.query as waiting_query, w.pid as w_pid, w.usename as w_user, l.query as locking_query, l.pid as l_pid, l.usename as l_user, n.nspname || '.' || c.relname as tablename from pg_stat_activity w join pg_locks l1 on w.pid = l1.pid and not l1.granted join pg_locks l2 on l1.relation = l2.relation and l2.granted join pg_stat_activity l on l2.pid = l.pid join pg_class c on c.oid = l1.relation join pg_namespace n on n.oid=c.relnamespace where w.waiting;
- 查询到阻塞的表及模式信息后,请根据会话ID结束会话:
1
SELECT PG_TERMINATE_BACKEND(PID);
- 这种情况一般是因为业务调度不太合理,建议合理安排各个业务的调度时间。
- 还可以通过设置GUC参数lockwait_timeout,控制单个锁的最长等待时间,即单个锁的等待超时时间。
lockwait_timeout单位为毫秒(ms),默认值为20分钟。
lockwait_timeout参数属于SUSET类型参数,请参考设置GUC参数中对应的设置方法进行设置。