关于pg杀会话的一些问题
pg_terminate_backend(pid)存储过程,第二是通过pg_ctl SIGNAL <pid>。这两种方法实际上都是给backend进程发了一个signal,让相关进程接到这个singal后,做相关的操作。这个signal包括SIGTERM/SIGINT/SIGABRT/SIGHUP SIGQUIT等。其中SIGHUP是用于重新装载参数(部分参数不一定起作用),SIGINT是重新初始化等等。当一个backend进程接收到SIGTERM的时候,就会主动进行进程相关的清理,包括释放包括锁在内的资源,然后关闭进程。
大家一定注意到了,这些信号里不包含SIGKILL。因为任何unix进程收到SIGKILL后,会不做任何处置,直接退出。在Oracle中,对进程异常退出的处理还是比较强大的,后台进程pmon会负责死进程和会话的清理工作,当有任何一个进程出现问题异常死掉后,会由pmon做善后工作,释放相关的资源,并且做一些善后修复工作,让数据库实例不会因为某个进程异常终止而受到影响,因此在Oracle数据库中,除非是核心后台进程异常终止才会终止数据库实例,其他的会话出现问题,都不会造导致数据库宕机。而实际上oracle的这个强大的能力也是在不断完善了十多年后才达到现在的水平的。我刚刚做dba的时候,处理未正常清除的分布式事务,释放被死会话占用的行锁是一项高级技巧,处理一次都是以数万计酬的。这种情况就是因为进程异常退出后pmon未能正确清理资源。
PostgreSQL不存在pmon这样的后台进程。另外当某个backend进程收到SIGKILL后直接退出,如果这个backend正在修改一段共享内存,而整个修改操作只做到一半,这个时候收到了SIGKILL命令,这个进程会放弃所有的操作,不做任何清理工作而直接退出。这种情况下,很可能共享内存被损坏了,整个数据库实例就会受到影响,这种情况下,很可能导致PostgreSQL实例宕机。
基于这种原因,PG的老鸟都会告诫新手千万不要像Oracle一样随意kill进程。也有些新手也尝试过kill -9去杀backend进程,似乎也屡屡得手,没有导致宕机。这是因为老白说的这种影响并不是每次都会发生的,如果运气好,你杀掉了backend,没有出现共享池的错误,那么就不会导致实例宕机。
随着
PG数据库版本的
更新,
PG对于这种情况的容错能也越来越强,因此
在早期的版本中,kill –
9 <
pid>
更容易造成PG实例宕机,而新一些的版本中,
宕机几率会低一些。
虽然是这样,我们在杀backend的时候,也不建议直接使用kill -9,而是首选pg_terminate_backend或者pg_ctl signal <pid>的方法。因为一般你要杀的backend进程往往都是存在一些问题,或者正在执行一个大查询的,这种情况下,kill -9导致共享内存受损的概率很高。
如果你要用Kill命令,也首先使用kill <pid>,因为kill <pid>实际上也是向这个进程发了一个SIGTERM信号,相当于执行了pg_ctl SIGTERM <pid>。
实际上我们还经常会遇到这样一种情况,pg提供的杀会话的手段并不起作用。命令执行后backend依然存在。实际上如果你遇到这种情况,用ps命令查看的时候会发现这个进程是出于D状态,这种状态的进程处于不可中断的内核调用中,是收不到任何signal的,因此这些杀会话的方法注定是无效的。如果遇到这种情况,你的linux可能出现了一些问题,或者遇到了某个bug。有时候甚至kill-9也杀不掉这个进程。如果这个backend占用的资源,比如锁,并不影响关键业务,那么你还是等非关键业务时间的时候再尝试kill-9,实在不行就只能申请重启pg数据库,甚至有些时候必须重启os了。另外这种情况出现,有时候是io子系统出问题了,这种时候不能只是简单的重启数据库和os,排查出io子系统存在的问题更为重要。
《关于pg杀会话的一些问题》来自互联网,仅为收藏学习,如侵权请联系删除。本文URL:http://www.bookhoes.com/2226.html