今天应用反映数据库很慢,有些SQL执行一天都没执行完,数据库版本为 8.3。
检查数据库,发现大量会话在更新同一张表 tbl_tmp, 产生大量行锁申请等侍。等于等侍状态的SQL (被堵住的SQL)。
查找等待状态的SQL
1 |
anpstat=# select datname,procpid,query_start,current_query,waiting,client_addr from pg_stat_activity where waiting='t'; |
查找正在执行的语句
1 |
sanpstat=# select datname,procpid,query_start,current_query,waiting,client_addr from pg_stat_activity where waiting='f' |
使用pg_cancel_backend()杀会话
1 |
sanpstat=# select pg_cancel_backend(2012); |
用 pg_cancel_backend()
杀进程,虽然显示为 ‘t’ ,但进程还在,文档上解释 Cancel a backend's current query
,猜想pg_cancel_backend()
只能 kill select 语句,而不能kill update语句,后来实验也证实了这一点,有兴趣的朋友可以自己做实验去验证下。
1 |
kill -9 杀进程 |
这里将正在执行的update tbl_tmp 表的会话kill 掉.
数据库无法连接
1 |
[enterprisedb@sanp-rich-db1 ~]$ psql -h 192.168.3.27 -p 1921 -d postgres -U rmt_db_bak |
备注:进程kill -9 以后,发现数据库无法连接,遭了,还好是个测试库。
数据库处于恢复模式
1 |
-bash-3.2$ ps -ef | grep post |
发现Postgresql 处于 recovery 状态,奇怪,Postgresql 恢复过程中是不允许连接的,在这点上,Oracle似乎要友好些
结论
- postgresql 8.3.3的版本 只提供系统函数 pg_cancel_backend(pid int) 杀进程,但是,这个函数只能 kill Select 查询,而updae,delete DML不生效,感兴趣的朋友可以自己做实验验证下;
- postgresql 8.4 以后版本提供 函数 pg_terminate_backend(pid int), 这个函数功能比前者强大,可以kill 各种DML(SELECT,UPDATE,DELETE,DROP)操作;
- 对于Postgresql ,最好不要用kill -9 去杀用户进程,因为如果是一个很大的UPDATE,kill后,Postgresql需要很长的时间做Recovery,而在这个RECOVERY过程中,数据库是不可用的,在这点上,Oracle 要友好些,在数据库恢复的过程中数据库依然可用,不太需要因Kill -9 用户进程而造成数据库不可用的情况。
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/236331.html