有网友反馈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后记的更多相关文章

  1. pymongo "ServerSelectionTimeoutError: No servers found yet" 错误的解决

    系统转移过程中,擅自把aptitude安装的mongoengine换成了pip安装,系统启动以后,报这个错误 报错提示: File "/usr/local/lib/python2.7/dis ...

  2. 使用PyMongo访问需要认证的MongoDB

    Windows 10家庭中文版,Python 3.6.4,PyMongo 3.7.0,MongoDB 3.6.3,Scrapy 1.5.0, 前言 在Python中,使用PyMongo访问Mongod ...

  3. 《C编译器剖析》后记

    这本书的序言.后记写的都让我很有感触!mark: 后 记 总有曲终人散时,不知不觉我们已经完成了对UCC 编译器的剖析,一路走来,最深的体会仍然是“纸上得来终觉浅,绝知此事要躬行”.按这个道理,理解U ...

  4. Python: Windows 7 64位 安装、使用 pymongo 3.2

    官网tutorial:  http://api.mongodb.com/python/current/tutorial.html 本教程将要告诉你如何使用pymongo模块来操作MongoDB数据库. ...

  5. 2.0 (2)测试pymongo

    在数据库中创建数据库.表,插入数据. from pymongo import MongoClient host = "localhost" port = 27017 client ...

  6. Windows平台下为Python添加MongoDB支持PyMongo

    到Python官网下载pymongo-2.6.3.win-amd64-py2.7.exe 安装pymongo-2.6.3.win-amd64-py2.7.exe 参照官方的用例进行测试 打开命令提示符 ...

  7. 【Python】pymongo使用

    官方文档:http://api.mongodb.com/python/current/index.html MongoReplicaSetClient:http://api.mongodb.com/p ...

  8. SpringMVC学习系列-后记 解决GET请求时中文乱码的问题

    SpringMVC学习系列-后记 解决GET请求时中文乱码的问题 之前项目中的web.xml中的编码设置: <filter> <filter-name>CharacterEnc ...

  9. 【mongo】pymongo通过_id删除数据

    来源:http://www.educity.cn/wenda/361741.html pymongo 根据 objectId _id 来删除数据想要删除数据,根据_id ,是最靠谱的,具体方法因为 _ ...

随机推荐

  1. 微信H5支付demo

    首先我们必须得在微信公众平台和微信商业平台那边配置好相关配置 1.注册微信服务号,开通微信支付权限绑定微信商业平台(这个具体怎么操作我就不说了) 2.获取应用(公众号)appid.应用(公众号)秘钥. ...

  2. opencv---颜色空间转化并实现物体跟踪

    一.图像处理的基本操作 因为这是第一篇写opencv的笔记,故先讲讲在python下写opencv的基本操作.总共总结了三点如下: 开头一定要加编码声明:-*- coding: utf-8 -*- p ...

  3. idea 项目 版本控制文件

  4. 查询Redis缓存

    package me.zhengjie.monitor.rest; import me.zhengjie.common.aop.log.Log; import me.zhengjie.monitor. ...

  5. linux配置和查看环境变量

    环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,比如临时文件夹位置和系统文件夹位置等等. 一.Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1.永久的:需要 ...

  6. EXAM-2018-8-9

    EXAM-2018-8-9 B 水题 注意理解题意 有坑 G 博弈 观察发现 总是会进行到最后两个,或者先手取完全部,再特判一下只有一张牌的情况 H 九连环 通过找规律 我们可以得出递推式: F[n] ...

  7. android流式布局、待办事项应用、贝塞尔曲线、MVP+Rxjava+Retrofit、艺术图片应用等源码

    Android精选源码 android模仿淘宝首页效果源码 一款艺术图片应用,采用T-MVVM打造 Android MVP + RxJava + Retrofit项目 android流式布局实现热门标 ...

  8. chkconfig原理

    ll  /etc/rc.d    里面有运行级别对应的脚本 chkconfig --list  sshd ll /etc/rc.d/rc3.d/   | grep sshd     (查看3启动 里面 ...

  9. JVM如何判断对象能否被回收

    •写在前面说起Java和C++,很容易想到让人疯狂的指针,Java使用了内存动态分配和垃圾回收技术,让我们从C++的各种指针问题中摆脱出来,更加专心于业务逻辑,不过如果我们需要深入了解java的JVM ...

  10. 源码中TODO、FIXME和XXX的含义

    前言: 今天在阅读Qt  Creator的源代码时,发现一些注释中有FIXME英文单词,用英文词典居然查不到其意义! 实际上,在阅读一些开源代码时,我们常会碰到诸如:TODO.FIXME和XXX的单词 ...