MongoDB timeout pthread

来源:互联网 发布:大型网络配置实例 编辑:程序博客网 时间:2024/05/07 05:52

最近的博客都是关于c++中遇到的问题。之前写过用codeblock作为ide来写,唯一的缺陷就是变量感知做的不到位。在网上搜了一番,发现netbeans的variable inspection做的最好,eclipse也不错。可惜这些强大的功能依赖于jvm,不属于轻量级ide。但这点编写时的性能开销在目前电脑上已经可以忽略了,换来的是巨大的便利性。更改theme也十分简单,唯一问题是选定高亮的黄色会覆盖字体,在 工具-选项-字体和颜色-语言(c++)-标记实例-背景 里更换。


回到正题,最近用MongoDB在c++下配置好以后,老问题又出现了,长时间使用游标会出现cursor死掉的问题。这个问题我在java driver中可以轻松的在find()后加addOption。但同样的问题在网上搜索了一圈,stack overflow和google group上有不少人问,却没有一个准确答案。其中有很多回答在 DBClientConnection 构建时加入一个timeout控制符。在管网上明确写着,这个时间是用于读写,而不是链接,链接固定5秒。但实际试了下,无论读取cursor中东西有多频繁,依旧会造成游标死亡。


这么常见的应用场景却很难找到解答,官网说明示例中也没有,实在觉得有些说不过去,最后我只得去api documentation里寻找。发现query类里有个findN和findOne,可以加入queryoption,但是说明却建议用于搜寻少量文档时才使用此方法,常规应用还是应该con.query()来解决。问题没解决,但好消息是c++驱动力是提供query option的。在DBClientConnection中的query里其实就有了例子:

con.query("localhost", BSONObj(),0,0,NULL,QueryOption_NoCursorTimeout);

参数依次为:1. 数据集名称 2. Query 3. 返回个数 4. 掠过个数 5.返回键值 6. 控制符。这时问题迎刃而解,在最后加上QueryOption_NoCursorTimeout即可保证cursor一直工作


在把程序从java改写成c++时遇到了多线程的问题,找遍整个网络,试了多种方法都不起作用。在stack overflow上发了个求助贴,结果因为程序代码无法重现问题而违规了。事实上我遇到的问题程序不可能reproduce,有很多本地的数据库信息和图片。在试图重写一个简短程序来重现问题时,却发现工作正常。原来思索许久的问题,根本处在其它一个地方,误打误撞的受到了启发,在这里也记录。


场景很简单,从数据库A中取BSONDoc,进行计算两较大的处理,插入数据库B,用多线程来实现。遇到的问题时经过了一段时间后,出现无法捕捉的异常。一开始还看不出异常信息,后来用回老版本的compatible版本,显示类似recv() message len is invalid。因为能正常工作很长时间,例如经常能工作40分钟插入1万3左右的数据才出现问题。以为是插入的connection用法不对。在c++driver中,有DBconnection和scopedconnection两种,所有介绍都说在多线程中要使用scoped那个链接池,但我亲自测试发现无论用哪个类链接,无论是在每个线程里自己创建,还是在一个函数中用scoped_ptr封装,问题都没解决。


在写程序想重现这一问题时,自己造了很多数据插入而不是从数据库A中提取,而这是问题竟然解决了。目前看来,问题是出现在数据库A中创建的那个cursor。使用多线程时,在主程序中创建cursor,以指针形式传给线程函数,使用more和next来调。这么看来,cursor并不是线程安全的东西,虽然有时能正常工作。解决办法自然是给cursor都取是上个锁就好了。在插入时我选择了简单每个线程自己创建个普通的dbconnection,没有按照大多数网上推荐的。在数据库端肯定是有写入锁的,所以不想在程序端再加个锁增加开销。


习惯了java中有个synchronized的关键字,目前c++中还要靠手动实现。这个问题断断续续困扰了我两个月,一直在其它方面寻找解决办法,却忽略了问题其实很简单,只不过来自其它方面而已。 you can not see clear when it is too close.


0 0
原创粉丝点击