如果一个Oracle DBA去运维PostgreSQL数据库,最容易犯的错误是就是杀进程把数据库给搞宕了。kill -9去杀一个Oracle用户进程是十分安全的,DBA可以十分大胆的去做,但是在PostgreSQL里,这个动作很可能会导致数据库实例宕机。PostgreSQL推荐大家使用的杀backend进程的方法有两种,第一种是使用pg_terminate_backend(pid)存储过程,第二是通过pg_ctl SIGNAL <pid>。这两种方法实际上都是给backend进程发了一个signal,让相关进程接到这个singal后,做相关的操作。这个signal包括SIGTERM/SIGINT/SIGABRT/SIGHUP SIGQUIT等。其中SIGHUP是用于重新装载参数(部分参数不一定起作用),SIGINT是重新初始化等等。当一个backend进程接收到SIGTERM的时候,就会主动进行进程相关的清理,包括释放包括锁在内的资源,然后关闭进程。大家一定注意到了,这些信号里不包含SIGKILL。任何进程收到SIGKILL后,会不做任何处置,直接退出。大家都知道,Oracle的后台进程pmon就是负责死进程和会话的清理工作的,当有任何一个进程出现问题异常死掉后,会由pmon做善后工作,释放相关的资源,并且做一些善后修复工作,让数据库实例不会因为某个进程异常终止而受到影响,因此在Oracle数据库中,除非是核心后台进程异常终止才会终止数据库实例,其他的会话出现问题,都不会造导致数据库宕机。而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>。