【问题标题】:How to get rid of cursor id error in mongodb?如何摆脱 mongodb 中的光标 id 错误?
【发布时间】:2015-12-20 06:33:42
【问题描述】:

我在 pymongo 中尝试过以下命令:

records= db.collection_name.find({"gender":"female"}).batch_size(5)

但经过几次迭代后:

pymongo.errors.CursorNotFound: Cursor not found, cursor id: 61593385827.

如果我在同一命令中尝试timeout=False,即

records= db.collection_name.find({"gender":"female"},timeout=False).batch_size(5) 

它给了

TypeError: __init__() got an unexpected keyword argument 'timeout' error.

【问题讨论】:

标签: python mongodb pymongo


【解决方案1】:

请显示更多您的代码。我怀疑你的光标 只是过期

mongodb manual中所述

默认情况下,服务器会在 10 点后自动关闭光标 不活动的分钟数或客户端是否已用尽光标。

这意味着,在您创建光标records 并通过使用一次将其耗尽之后,例如,像

mylist = [ i for i in records]

您的 records 光标不再存在

另请参阅thisthis 问题

【讨论】:

    【解决方案2】:

    尝试在查询中设置no_cursor_timeout=True,如下所示:

    records= db.collection_name.find({"gender":"female"}, no_cursor_timeout=True).batch_size(5)

    【讨论】:

      【解决方案3】:

      设置timeout=False 是一种非常糟糕的做法。摆脱 cursor id 超时异常的更好方法是估计您的循环在 10 分钟内可以处理多少个文档,并得出一个保守的批量大小。这样,只要前一批中的文档用完,MongoDB 客户端(在本例中为 PyMongo)就必须不时地查询服务器。这将使光标在服务器上保持活动状态,并且您仍将受到 10 分钟超时保护的保护。

      以下是设置游标批量大小的方法:

      for doc in coll.find().batch_size(30):
          do_time_consuming_things()
      

      【讨论】:

        【解决方案4】:

        现在是 2021 年,答案是:

        • 老:no_cursor_timeout=True 可行

        • 新:no_cursor_timeout=True 无效,应改为

          • 明确创建会话,并且所有操作(获取数据库、获取集合、查找等)都应使用该会话
          • 然后定期更新/刷新会话(保持活动状态,未过期)
            • 示例代码
        import logging
        from datetime import datetime
        import pymongo
        
        mongoClient = pymongo.MongoClient('mongodb://127.0.0.1:27017/your_db_name')
        
        # every 10 minutes to update session once
        #   Note: should less than 30 minutes = Mongo session defaul timeout time
        #       https://docs.mongodb.com/v5.0/reference/method/cursor.noCursorTimeout/
        # RefreshSessionPerSeconds = 10 * 60
        RefreshSessionPerSeconds = 8 * 60
        
        def mergeHistorResultToNewCollection():
        
            mongoSession = mongoClient.start_session() # <pymongo.client_session.ClientSession object at 0x1081c5c70>
            mongoSessionId = mongoSession.session_id # {'id': Binary(b'\xbf\xd8\xd...1\xbb', 4)}
        
            mongoDb = mongoSession.client["your_db_name"] # Database(MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True), 'your_db_name')
            mongoCollectionOld = mongoDb["collecion_old"]
            mongoCollectionNew = mongoDb['collecion_new']
        
            # historyAllResultCursor = mongoCollectionOld.find(session=mongoSession)
            historyAllResultCursor = mongoCollectionOld.find(no_cursor_timeout=True, session=mongoSession)
        
            lastUpdateTime = datetime.now() # datetime.datetime(2021, 8, 30, 10, 57, 14, 579328)
            for curIdx, oldHistoryResult in enumerate(historyAllResultCursor):
                curTime = datetime.now() # datetime.datetime(2021, 8, 30, 10, 57, 25, 110374)
                elapsedTime = curTime - lastUpdateTime # datetime.timedelta(seconds=10, microseconds=531046)
                elapsedTimeSeconds = elapsedTime.total_seconds() # 2.65892
                isShouldUpdateSession = elapsedTimeSeconds > RefreshSessionPerSeconds
                # if (curIdx % RefreshSessionPerNum) == 0:
                if isShouldUpdateSession:
                    lastUpdateTime = curTime
                    cmdResp = mongoDb.command("refreshSessions", [mongoSessionId], session=mongoSession)
                    logging.info("Called refreshSessions command, resp=%s", cmdResp)
                
                # do what you want
        
                existedNewResult = mongoCollectionNew.find_one({"shortLink": "http://xxx"}, session=mongoSession)
        
            # mongoSession.close()
            mongoSession.end_session()
        

        详情请参考another post answer

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多