【问题标题】:GridFS put command hangs from pymongo when used within a transactionGridFS put 命令在事务中使用时从 pymongo 挂起
【发布时间】:2018-08-08 21:45:50
【问题描述】:

我正在使用 GridFS 在我的数据库中存储一些视频文件。我已经更新到 MongoDB 4.0 并尝试使用多集合事务模型。我面临的问题是put() 命令gridfs 挂起系统。我的使用方式如下:

client = pymongo.MongoClient(mongo_url) 
db = client[db_name]
fs = gridfs.GridFS(db)

现在我尝试使用如下事务模型:

with db.client.start_session() as session:
    try:
        file_path = "video.mp4"  
        session.start_transaction()

        with open(file_path, 'rb') as f:
            fid = self.fs.put(f, metadata={'sequence_id': '0001'})
        session.commit_transaction()
    except Exception as e:
        raise
    finally:
        session.end_session()

问题是put 命令挂起大约一分钟。然后它返回但提交失败。我有一种感觉,这是因为会话对象没有传递给put 命令,但我在帮助中没有看到任何将会话作为输入的参数。挂起后,测试失败,堆栈如下:

Traceback(最近一次调用最后一次):

    session.commit_transaction()
  File "/Users/xargon/anaconda/envs/deep/lib/python3.6/site-packages/pymongo/client_session.py", line 393, in commit_transaction
    self._finish_transaction_with_retry("commitTransaction")
  File "/Users/xargon/anaconda/envs/deep/lib/python3.6/site-packages/pymongo/client_session.py", line 457, in _finish_transaction_with_retry
    return self._finish_transaction(command_name)
  File "/Users/xargon/anaconda/envs/deep/lib/python3.6/site-packages/pymongo/client_session.py", line 452, in _finish_transaction
    parse_write_concern_error=True)
  File "/Users/xargon/anaconda/envs/deep/lib/python3.6/site-packages/pymongo/database.py", line 514, in _command
    client=self.__client)
  File "/Users/xargon/anaconda/envs/deep/lib/python3.6/site-packages/pymongo/pool.py", line 579, in command
    unacknowledged=unacknowledged)
  File "/Users/xargon/anaconda/envs/deep/lib/python3.6/site-packages/pymongo/network.py", line 150, in command
    parse_write_concern_error=parse_write_concern_error)
  File "/Users/xargon/anaconda/envs/deep/lib/python3.6/site-packages/pymongo/helpers.py", line 155, in _check_command_response
    raise OperationFailure(msg % errmsg, code, response)
pymongo.errors.OperationFailure: Transaction 1 has been aborted.

编辑

我尝试将 put 块替换为:

try:
   gf = self.fs.new_file(metadata={'sequence_id': '0000'})
   gf.write(f)
finally:
   gf.close()

但是,gf.close() 再次发生挂起

我还尝试直接实例化GridIn,以便我可以提供会话对象,但失败为:

gin = gridfs.GridIn(root_collection=self.db["fs.files"], session=session)
gin.write(f)
gin.close()

此操作失败并显示错误消息:

It is illegal to provide a txnNumber for command createIndexes

【问题讨论】:

    标签: mongodb transactions pymongo gridfs


    【解决方案1】:

    问题是 put 命令挂了大约一分钟

    self.fs.put() 的第一次尝试实际上并没有使用transactions,只是花了一段时间才上传文件。

    然后在尝试提交(空)事务时上传完成后,不幸的是,由于上传所花费的时间,事务达到了最大生命周期限制。见transactionLifetimeLimitSeconds。默认限制已设置为 60 秒以设置最大事务运行时间。

    如果您正在考虑提高此限制,请记住,当事务快照创建后写入量进入 MongoDB 时,WiredTiger 缓存压力会增加。这种缓存压力只有在事务提交后才能释放。这就是 60 秒默认限制背后的原因。

    为命令 createIndexes 提供 txnNumber 是非法的

    首先,影响数据库目录的操作(例如创建或删除集合或索引)在多文档事务中不允许

    PyMongo GridFS 的代码正在尝试为 GridFS 集合创建索引,当与事务会话一起使用时,服务器上禁止这样做(您可以使用会话但不能使用事务)。

    我已经更新到 MongoDB 4.0 并尝试使用多集合事务模型

    我建议对 GridFS 使用普通的数据库操作。 MongoDB multi-document 事务旨在用于多文档原子性。我认为在文件上传案例中没有必要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-25
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多