https://docs.oracle.com/cd/E11882_01/server.112/e40540/toc.htm
Zephir Documentation
https://docs.zephir-lang.com/0.12/en/motivation
zephir是为开发PHP扩展而发明的一门语言,而且只能用来开发PHP扩展,通常,PHP的扩展都是编译运行的,但是zephir却是把自己编译成字节码给zend解释执行的,但是他也能进一步编译成机器语言
Zephir was not created to replace PHP or C. Instead, we think it is a complement to them, allowing PHP developers to venture into code compilation and static typing. Zephir is an attempt to join good things from the C and PHP worlds, looking for opportunities to make applications faster.
只能写带名字空间的class
Code in Zephir must be placed in classes. The language is intended to create object-oriented libraries/frameworks, so code outside of a class is not allowed. Additionally, a namespace is required:
他可以直接调用PHP语言定义的函数
必须写注释:
In most languages, comments are simply text ignored by the compiler/interpreter. In Zephir, multi-line comments are also used as docblocks, and they’re exported to the generated code, so they’re part of the language!
If a docblock is not located where it is expected, the compiler will throw an exception.
zephir相当于是跑在zend上的另一门语言
为什么会有NewSQL? – rocketluoqq的博客 – CSDN博客
db2查看当前连接的数据库是哪个
办法1: 不知道
办法2:
把现有的db2 connect to 。。,db2 connect reset等用bash的function包装一下,在包装函数里面添加逻辑,不直接db2使用原生的方法
linux 调试工具之perf-tools
- 实时查看系统正在派生哪些进程:
- execsnoop 不能跟踪到clone出来的进程
- 实时查看系统正在打开哪些文件:
- 实时查看哪些进程在访问IO以及IO延迟:
- 更加方便地分析IO延迟:
- 查看IO请求的块儿大小分布情况:
- cache大小及命中率分析:
- 系统调用次数分析:
- 查看tcp连接异常:
注意:
1) 这里的重传是内核层面的,如果应用层设置连接超时为1s,失败则重新连接,则不算重传,也基本不会触发内核层的重传
2) 这里的PID通常为零,因为重传操作基本都是内核触发的超时重传 - 查看慢的内核函数调用:
DB2 自动化脚本引发的思考
实用的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#!/bin/bash DB=$1 db2 connect to $DB || exit #### 提取所有表名到变量tables # 错误的写法 tables=$(db2 -x list tables | awk '{print $1}') # 正确的写法 (这一定不是最简洁的,但是逻辑很清晰) tmp=$(db2 -x list tables) tables=$(echo "$tmp"| awk '{print $1}' ..... |
脚本基本逻辑是:
- 连接数据库
- 获取所有表的表名
- 然后做想做的事(如:导出表数据)
脚本很简单,但是,还是写出问题来了
其实,短短的代码里面藏着很多知识呢
上述的错误的写法之所以错,是因为db2进程的PPid不是当前的bash,但是和正确的写法差别不大呀,为什么PPid就不一样了呢? 可以参考: https://phpor.net/blog/post/12836
为什么db2 那么关心PPid ?可以参考:https://phpor.net/blog/post/12806
更新:
就算非常小心的去写,bash中通过函数内部使用db2命令,很容易就进入的不同的环境,所以,为了能让db2和bash很好的结合,我创造了一个db2cli,其架构就是:
bash中定义函数调用自定义的db2函数,该db2函数内部通过curl访问一个httpserver,让本次会话的db2命令都在同一个httpserver进程内部执行,httpserver地址:https://github.com/phpor/go-example/tree/master/app/db2-proxy
db2cli地址:
bash之返回值判断
场景:
想执行一个命令,如果命令成功,则不输出任何信息,如果命令失败,输出错误信息;
通常来讲,特别简单:
1 |
$cmd >/dev/null || exit $? |
就行; 但是,如果 $cmd 会通过标准错误输出一些debug信息呢?这样的话,即使命令成功也会看到一些不必要的信息,那么如何改进呢?
基本思路就是,把标准输出扔掉(可选),标准错误重定向到标准输出,然后赋值给一个变量:
1 |
x=$(no_such_cmd 2>&1); [[ $? -ne 0 ]] && echo $x |
这个没有问题;
但是,当我们试图把这个逻辑写到函数中时,似乎就不太对了,因为函数中的变量尽量local声明,而且,声明和赋值写在一起显得紧凑、美观、有修养;如下:
1 2 3 4 |
function xx() { local x=$(no_such_cmd 2>&1) [[ $? -ne 0 ]] && echo $x } |
这是,和我们预期不一样了 ; $? 已经不是no_such_cmd 的返回值了,为什么?
参看下面截图:
显然,第一个函数中 $? 其实是local语句的返回值了(local的返回值和变量被赋了什么值没有关系,参看: help local),所以,正确的姿势是,先声明变量,再使用
从db2 connect to 看进程关系
问题:
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中执行的,如下:
db2之事务日志大小
通过 db2 get db cfg |grep -i log 查看事务日志相关配置,也可以看到事务日志文件的位置
通过 :
1 2 3 |
db2 update db cfg for $DB USING LOGFILSIZ 32768 db2 update db cfg for $DB USING LOGPRIMARY 10 db2 update db cfg for $DB USING LOGSECOND 10 |
修改事务日志的文件大小及文件个数,修改后可以通过:
1 2 |
db2 deactive database $DB db2 active dabase $DB |
是修改生效,会发现事务日志的文件大小和文件数量都发生了变化
db2look 导出sql文件乱码的原因
使用db2look导出的sql文件根据当前环境不同生成的文件编码也不同;
原因1:
如果LANG=zh_CN.UTF-8 ; db2set db2codepage=gbk ; 则会导致文件的第一部分包含utf-8 编码的汉字:
而文件的sql部分中的汉字则是gbk的;
那么,该文件的编码就不能被正确识别; 所以,较好的做法是,使用db2look时,设置 LANG=C, 这样的话Timestamp部分就不会显示中文了; 而sql中的汉字编码跟随db2set 中的db2codepage,建议设置为数据库的字符集和编码,一方面可以避免字符集的转换,另一方面,不通字符集之间不见得就是能转换的,转换失败的话就转成 问好(?) 了。另外,导出的文件在自己的终端打开时,可能和终端的字符集编码不一致导致查看时乱码,这个并不紧要,如果终端的LANG设置正确的话,通常vim会自动将文件的编码转码为终端的编码(vim通过LANG来检测终端的编码)的。
原因2:写入数据库的编码确实就是不同的,下图正常显示的是utf-8 编码的,不正常显示的是写入的gbk编码当做utf-8 解释了; 但是,这种错误不易被发现,因为执行的时候会被认为是合法的utf-8的(确实真的合法)
真实的将,该截图是vim查看后截图的,vim根据当前环境将文件原本的GBK自动转码为utf8显示的,乱码部分是原本的GBK文件中的utf8字符又往utf8转了一次所致
如果使用vim查看总是看到满屏的乱码,可能就是识别错编码了,比如:识别成了utf-16; ,因为所有的文件都可以认为是有效的utf-16的。