问题:
db2 connect to XXX 究竟做了什么,使得 后续的db2 进程就知道自己当前上下文的数据库是XXX ?而且,不同的bash进程下都有自己单独的上下文,不相互影响。
- 如果不考虑多个bash之前的相互影响,则,进程间共享信息的办法有很多,比如: 文件;
- 但是db2在不同的bash中分别db2 connect to 是不相互影响的,如果不是文件又是什么呢?
分析:
- 在db2 connect to 之后,执行:
strace -fF -o /tmp/strace.txt db2 list tables- 很不幸:进程hang住,不退出了
- 很庆幸,我正好可以看看当前db2 在干啥
- 通过ps找不到db2 list tables进程
- 分析strace.txt:
26900 进程就是db2 list tables ; 不过该进程早就离开了,从下图可以知道,该进程是生了26901后离开的
然而,当我们回过神儿来的时候,26901也不见了,因为 26901 干的活也不多:
26901 基本也就是生了个26902 就完事儿了,26902 是我们目前还能够看到的一个进程,就是:
strace.txt 中是这样子的:
26902 进程当前是在执行msgrcv:
也就是说,每一个db2总是会化身成db2bp来工作的,而这个999718998 又是个啥?
ipc就是linux上进程间通信的机制,有三种方式: 共享内存、消息队列、信号量,都可以通过ipcs 查看,这里看到的999718998就是消息队列
可以进一步查看该消息队列的详细信息:
通过ipcs 我们可以发现db2大量使用了共享内存、消息队列、信号量,都用到了,其实,这扯的有点远了
回来我们发现db2bp是一个重要的进程,真正要连数据库的应该就是这个进程,该进程如何知道要连接那个数据库呢?
我们发现db2bp进程有3个参数,其中第一个参数的前一个部分 26895 正好是strace进程的进程ID:
这难道是巧合,其实不然,我们从一个新的bash中执行db2 connect to 就会产生一个db2bp进程:
而且该进程的参数中就包含当前bash进程的进程ID的,所以,该进程一定是db2 connect to 催生的,但是确实没有随着db2 进程的退出而死亡,所以,db2bp 是一个声明期很长的进程,这也是上面的strace没有能立即退出的原因所在;因为,strace跟踪的db2进程是在一个新环境中执行的,没有找到对应的db2bp进程,所以就启动一个db2bp进程,这里也可以顺便得出两个推论:
1. db2bp 进程不是只有db2 connect to 才会创建的,哪怕简单敲一个db2后回车都会催生对应的db2bp进程的,而且不会随着quit的执行而退出
2. db2bp 进程并不是一定就已经在connect着某个数据库的,主要是服务于db2 进程的
3. 尽管没有执行过db2 connect to ,如果我们执行过db2 的其它命令,也有必要db2 terminate ,这样才能使得db2bp 进程退出(事实上,db2bp足够聪明,可以在bash退出的时候退出的)
4. db2 connection reset 和 db2 terminate 的区别也是毕竟明显的,前者断开连接,后者退出db2bp进程
下图证明db2 terminate 可以结束db2bp进程:
关于db2 terminate 的更多细节可以参考: https://www.ibm.com/support/knowledgecenter/en/SSEPGG_10.5.0/com.ibm.db2.luw.admin.cmd.doc/doc/r0001973.html - 通过上述的分析,我们是不是可以推测,db2的上下文环境是通过父进程(当前shell)的PID来标识的呢?我们分析一下:
- 我们知道bash中可以通过圆括号让进程在新的子shell中执行的,如下:
- 然而,我们在db2 connect to 之后,不管是否把db2放在圆括号中都是可以的:
所以说,是不是可以得出结论:db2 的环境不仅仅是根据ppid来定义的。错,db2的环境确实是根据其ppid来定义的,参考: https://www-01.ibm.com/support/docview.wss?uid=swg21983930 ; 那么,上面圆括号的问题又如何解释呢? 参考: https://phpor.net/blog/post/12836 - 虽然基本已经水落石出了,但是难道就真的没法strace跟踪了吗?(因为strace总是给db2 执行一个新的环境)
- 其实,我们可以strace跟踪db2所在的bash进程
- 通过strace分析发现,主要通过msgsnd msgrcv msgget 来通过消息队列来实现和db2bp之间的进程通信的,而且消息队列的ID和进程的PPID有直接关系:
至于如何根据PPID算出msgget需要的key的,这个就需要看源码了,据说是hash出来的,那么,如果是terminate之后再执行db2 list tables 会是什么样的strace结果呢,看下图:
我们发现ppid是一样的,uid是一样的,msgget的key也是和上次一样的,只是这次get不到了,然后下面的逻辑就变了,就会去催生一个db2bp出来,这次的命令执行就会慢一些了
- 通过strace分析发现,主要通过msgsnd msgrcv msgget 来通过消息队列来实现和db2bp之间的进程通信的,而且消息队列的ID和进程的PPID有直接关系:
- 我们知道bash中可以通过圆括号让进程在新的子shell中执行的,如下: