bsddb3 DB.get / put挂起事务

时间:2018-04-20 03:52:16

标签: python-3.x berkeley-db bsddb

我对Berkeley DB很新,我试图在Python中使用它与bsddb3进行电源安全交易使用DB_AUTO_COMMIT并且没有事务参数读取和写入工作正常。但是当我通过手动事务调用get / put时,调用会无限期地挂起,几乎不使用CPU(大约50k周期/秒)并且不执行磁盘I / O.

    _data_store_env.log_set_config(bdb.DB_LOG_AUTO_REMOVE, True)
    _data_store_env.set_lg_max(256 * 2**20)
    _data_store_env.set_cachesize(0, 512 * 2**20)
    _data_store_env.set_lg_dir(str(_journal_path))
    _data_store_env.set_tmp_dir(str(tmp_dir))
    _data_store_env.open(str(_bulk_data_path), bdb.DB_CREATE | bdb.DB_INIT_LOCK | bdb.DB_INIT_LOG | bdb.DB_INIT_MPOOL | bdb.DB_INIT_TXN | bdb.DB_RECOVER | bdb.DB_THREAD)

    # Originally I simply used DB_AUTO_COMMIT, but I changed it to see if this way would fix the hang. It didn't.
    txn = _data_store_env.txn_begin()

    _data_store = bdb.DB(_data_store_env)
    _data_store.set_flags(bdb.DB_CHKSUM)
    _data_store.set_pagesize(65536)
    _data_store.open("filestore.db", None, bdb.DB_HASH, bdb.DB_CREATE | bdb.DB_THREAD, 0x660, txn)

    _idx_store = bdb.DB(_data_store_env)
    _idx_store.set_flags(bdb.DB_CHKSUM | bdb.DB_DUPSORT)
    _idx_store.open("idxstore.db", None, bdb.DB_HASH, bdb.DB_CREATE | bdb.DB_THREAD, 0x660, txn)
    _data_store.associate(_idx_store, lambda key, data: key[0:9], bdb.DB_IMMUTABLE_KEY, txn)

    txn.commit()
...
    # It doesn't matter whether this flag is present or not. Both produce the same result.
    txn = _data_store_env.txn_begin(None, bdb.DB_TXN_BULK)
...
    # Never returns
    file_exists = _idx_store.has_key(entry_key, txn)
...
    # Also never returns
    _data_store.put(file_hash, file_data, txn)

我做错了吗?交易甚至可以在bsddb3中使用吗?

1 个答案:

答案 0 :(得分:0)

使用本机代码调试器进行了几个小时的调试后,我相信我已经非常接近根本原因了。似乎在get / put调用中没有出现挂起,但在它之后 - 在get / put调用完成后调试器GUI执行的对数据库对象的 len 的调用(以及如果程序自由运行,则定期进行。这显然是陷入资源获取循环中,因为事务正在进行中,所以它永远不会完成(我没有用于构建bsddb3的符号 - 它静态链接到BDB,不会少 - 所以我不是有兴趣花时间弄清楚DB_length调用下调用堆栈中的十几个函数是什么)。这可能还与以下事实有关:当我将bsddb3引入项目时,任何调试器命令的响应时间增加到5秒(当它没有死锁时)。

总之,这似乎是试图使其变量窗口保持最新的调试器GUI与bsddb3 DB应该是映射的设计决策之间的有毒交互。我非常愿意接受如何解决这个问题的建议;我尝试了一些事情,但一直无法弄清楚如何从数据库对象中删除 len 方法(它是一个只读属性,因为它实现了在C)。现在我在DB周围创建一个不是序列的包装器;除非您意外地将鼠标悬停在数据库对象上并且调试器尝试获取其属性,否则会解决问题。