目录
2.6.1.1 pg_locks和pg_stat_activity的区别?
2.6.2.1 pg_cancel_backend和pg_terminate_backend的区别?
1. 背景
正常情况下,PostgreSQL只要连上了就能愉快地使用了,但是在一些特别的场景,如压测或者某些不可描述的异常,会出现数据库连接异常的情况,比如链接数占满了,无法释放的情况,这时,我们会猜测是不是数据库死锁了?或者链接数达到最大值了?
2. 常用SQL语句
2.1. 查询PostgreSQL设置的最大连接数
-- 查询最大连接数
SHOW max_connections;
2.2. 查询当前使用中的连接数
-- 查询当前连接数
SELECT COUNT(*) FROM pg_stat_activity;
针对上述情况,我列举了几个常用的sql语句,用于排查“死锁”问题
2.3. 查询当前所有连接数据库用户和用户其连接数
-- 查询当前所有连接数据库用户和用户其连接数(按用户名分组统计)
SELECT usename, COUNT(*) FROM pg_stat_activity GROUP BY usename ORDER BY count DESC;
-- 查询特定数据库用户当前连接数(your_db_user_name替换成自己的数据库名称)
SELECT COUNT(*) FROM pg_stat_activity WHERE usename = 'your_db_user_name';
2.4. 查询是否存在锁表记录
-- 显示出没有被授予的锁,也就是等待的锁
SELECT * FROM pg_locks WHERE granted = false;
-- 等价如下SQL
SELECT * FROM pg_locks WHERE granted = 'f';
2.5. 查询详细的锁信息
-- 查询更详细的锁信息,包括哪些语句在等待锁
SELECT a.datname,
l.relation::regclass,
l.transactionid,
l.mode,
l.GRANTED,
a.usename,
a.query,
a.query_start,
age(now(), a.query_start) AS "age",
a.pid
FROM pg_stat_activity a
JOIN pg_locks l ON l.pid = a.pid
WHERE NOT l.GRANTED;
2.6. 如何解锁?
2.6.1. 定位并终止阻赛的事务
在一般情况下,解锁最直接的方式就是终止导致锁表的进程或事务。首先要确定持有锁的事务,可以通过如下语句:
-- 确定持有锁的事务
SELECT * FROM pg_stat_activity WHERE waiting = 't';
2.6.1.1 pg_locks和pg_stat_activity的区别?
这两个视图查询的内容其实是不同的。具体选择用哪个视图,取决于你需要查询的信息。
SELECT * FROM pg_stat_activity;
SELECT * FROM pg_locks WHERE granted = false;
2.6.2. 查找到pid后,按pid终止进程
-- 按PID终止进程
SELECT pg_terminate_backend(PID);
2.6.2.1 pg_cancel_backend和pg_terminate_backend的区别?
pg_cancel_backend和pg_terminate_backend函数类似于UNIX中的SIGINT和SIGTERM信号。
-
pg_cancel_backend(PID):这个函数会发送一个请求来取消后端当前的查询。PID是你想要取消查询的进程的PID。这个效果类似于UNIX的SIGINT信号,查询会尽可能的安全取消,比如说在一个安全的点回滚到开始状态。
-
pg_terminate_backend(PID):这个函数会中断一个连接和该连接上的任何活动。PID是你想要终止的后端进程的PID。这个函数发送的是一个terminate(BSIGTERM)信号给指定的后端,使得后端进程立即退出。
2.7. 参考
ChatGPT