写文件的并发问题

来源:互联网 发布:炫酷个人博客php源码 编辑:程序博客网 时间:2024/05/21 17:41

      上周接到一个bug,大致情况是在tpcc测试中,数据库掉电6次,就会起不来。内部测试,因此有数据可供调试。对日志文件进行分析后,发现,主日志文件头后面紧接着的4k居然也是日志头格式,难怪日志解析出错!

      这就很令人费解了。检查日志代码中写日志头的代码,所有调用文件写的地方,偏移都没有错。第一反应是,莫非缓冲区溢出,导致日志缓冲区的内容被覆盖?这个也太邪乎了,如果是这样,问题还真不好找了。看了半天还是不得其解,郁闷死了。

      继续看代码,发现写文件的操作,有两个步骤,首先是SetFilePointer设置文件偏移,然后是调用WriteFile函数写。那会不会是两个线程共用句柄,同时写文件,结果一个误用了另外一个的偏移,将内容覆盖了?顺序如下:A:SetFilePointer;B:SetFilePointer;B:WriteFile;A:WriteFile。顺着这个思路,果然发现两个线程同时写日志文件,一个是日志刷盘线程,一个是检查点线程。分析日志文件,刚好被覆盖4K,文件号和页号刚好连续,正好印证了我的假设。

      如何修改?第一想到的是对两个操作进行同步,这个代价太高了。第二,用spin来处理,可以接受。我后来还是闲麻烦,因为检查点不频繁,我干脆就重新打开一个文件句柄得了。如果句柄不共享,也出现问题,那就操作系有问题了,不过呢,还有待验证。其实自己也可以写个简单的程序验证下的。

原创粉丝点击