码迷,mamicode.com
首页 > 其他好文 > 详细

pymongo bugfix后记

时间:2020-02-02 11:59:59      阅读:67      评论:0      收藏:0      [点我收藏+]

标签:ros   操作   flags   收获   流程   工具   osi   timestamp   err   

有网友反馈py-mongo-sync同步异常,检查发现curosr[0]取查询结果第一个文档时报错”no such item for Cursor instance”。

这里的逻辑是,根据timestamp查询oplog起始位置,cursor类型是TAILABLE,然后取出第一条oplog,验证timestamp是否一致。

对方mongo版本是v3.4,同步工具在v3.2及更早版本的MongoDB上还没出过类似问题。 使用pymongo 3.5.1(最新版本)分别用v3.2和v3.4跑同步测试,在query结果非空的情况下,v3.2正常,v3.4报错,怀疑是不是v3.4做了什么改动,导致dirver不兼容。

进一步排查,cursor[0]读取文档,db端返回了一个错误,意思说tailable和singleBatch两个选项冲突。

{'number_returned': 1, 'data': [SON([(u'ok', 0.0), (u'errmsg', u"cannot use tailable option with the 'singleBatch' option"), (u'code', 2), (u'codeName', u'BadValue')])], 'starting_from': 0, 'cursor_id': 0}

cursor.__getitem__(self, index)方法,如果取单个文档,首先对当前cursor进行clone,将limit设置为-1(db返回一条文档并关闭cursor,可参考ntoreturn vs batchSize),表示只读取一条文档。

 577         if isinstance(index, integer_types):                                                                                                                                            
 578             if index < 0:                                                                                                                                                               
 579                 raise IndexError("Cursor instances do not support negative "                                                                                                            
 580                                  "indices")                                                                                                                                             
 581             clone = self.clone()                                                                                                                                                        
 582             clone.skip(index + self.__skip)                                                                                                                                             
 583             clone.limit(-1)  # use a hard limit                                                                                                                                         
 584             for doc in clone:                                                                                                                                                       大专栏  pymongo bugfix后记     
 585                 return doc                                                                                                                                                              
 586             raise IndexError("no such item for Cursor instance")                                                                                                                        
 587         raise TypeError("index %r cannot be applied to Cursor "                                                                                                                         
 588                         "instances" % index)

cursor类型是TAILABLE或TAILABLE_AWAIT,所以query的tailable选项为True; cursor.limit设置为-1,导致query的singleBatch选项为True; 二者皆为True,引发冲突。

因为只读取一条文档,limit必须为-1,所以需要把TAILABLE和TAILABLE_AWAIT设置为0,避免选项冲突。

clone.limit(-1)  # use a hard limit  
clone.__query_flags &= ~CursorType.TAILABLE_AWAIT  # PYTHON-1371

至此,问题解决,说说几点收获:

  1. 尽量不要使用cursor索引访问文档,除非是一次性操作

     # 以下是原代码逻辑
     coll = self._src_mc['local'].get_collection('oplog.rs', codec_options=bson.codec_options.CodecOptions(document_class=bson.son.SON))
     cursor = coll.find({'ts': {'$gte': oplog_start}}, cursor_type=pymongo.cursor.CursorType.TAILABLE_AWAIT, no_cursor_timeout=True)
    		
     if cursor[0]['ts'] == oplog_start # 这里对原始cursor进行clone,执行查询(第一次),然后关闭cursor_cloned
    
         # 之前在跑同步时,时间戳一致,但此处可能仍有时间长短不一的等待,始终不明所以
         # 原因是下面在调用cursor.next()时会重新执行查询
    
         while True:
             oplog = cursor.next() # 这里使用原始cursor,执行查询(第二次)
             # handle oplog
    
  2. 提交PR前,确保本地跑通test case,当时仅考虑到TAILABLE的情况,而忽略了TAILABLE_AWAIT
  3. 掌握PR流程:提交PR后,如果review未通过,需要修改代码,在你的local分支下继续commit并push到GitHub,新commit会自动追加到该PR,最后由项目维护者完成merge,可以参考collaborating-with-issues-and-pull-requests
  4. 最后,很高兴PR能被官方merge :)

pymongo bugfix后记

标签:ros   操作   flags   收获   流程   工具   osi   timestamp   err   

原文地址:https://www.cnblogs.com/lijianming180/p/12251242.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!