前几天发表的《Postgresql完全刷缓存补丁》一文,其实稍微有点缺憾,就是没有语句中断机制。刷缓存过程是纯内存访问,理论上速度会非常快,而且以PG的机制,一个进程获得锁之后会立即释放,所以本文纯粹作为补充说明,演示如何实现。
另外,当前的缓存锁获取机制,是一直尝试,直到超时发出PANIC错误。
见:src/backend/storage/lmgr/s_lock.c 中的 s_lock 函数
我们从代码可以看到,在整个语句的执行过程中,经常出现CHECK_FOR_INTERRUPTS();,这就是中断检测。典型场景,我们在psql下运行一个长时语句,这时我们想中断它,按下Ctrl+C,最终就是这个宏在起作用。它的定义在src/include/miscadmin.h中:
#define CHECK_FOR_INTERRUPTS() \ do { \ if (InterruptPending) \ ProcessInterrupts(); \ } while(0)
ProcessInterrupts();的定义请自行查看,这里关键就是这个InterruptPending,它是在服务器端收到用户中断信号之后变为true。
这个信号的收取关系到cancel_key,每次启动后端进程会随机分配,客户端发送中断信号必须带有这个key作为证明,见src/backend/postmaster/postmaster.c中的processCancelRequest()函数。
要吃饭了,到这里其实就已经很明白,偷个懒,不继续写了。