bsddb3 DB.get/put 挂起事务
Posted
技术标签:
【中文标题】bsddb3 DB.get/put 挂起事务【英文标题】:bsddb3 DB.get/put hangs with transaction 【发布时间】:2018-04-20 03:52:16 【问题描述】:我对 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】:在使用本机代码调试器进行数小时调试后,我相信我已经非常接近根本原因。似乎挂起不会发生在 get/put 调用中,但在它之后 - 在 get/put 调用完成后调试器 GUI 对数据库对象执行的 len 调用中(以及如果程序免费运行,则定期进行)。这显然陷入了一个永远不会完成的资源获取循环中,因为事务正在进行中(我没有用于构建 bsddb3 的符号 - 它静态链接到 BDB,不少于 - 所以我对花费是时候弄清楚 DB_length 调用下方的调用堆栈中的十几个函数是什么了)。这也可能与我在项目中引入 bsddb3 时对任何调试器命令的响应时间增加到大约 5 秒(当它没有死锁时)这一事实有关。
总而言之,这似乎是调试器 GUI 试图使其变量窗口保持最新与 bsddb3 DB 应该是映射的设计决策之间的有害交互。我非常愿意接受有关如何解决此问题的建议;我尝试了一些方法,但无法弄清楚如何从 DB 对象中删除 len 方法(它是一个只读属性,因为它是用 C 实现的)。现在我正在围绕不是序列的数据库创建一个包装器;除非您不小心将鼠标悬停在 DB 对象上并且调试器尝试获取其属性,否则这可以解决问题。
【讨论】:
以上是关于bsddb3 DB.get/put 挂起事务的主要内容,如果未能解决你的问题,请参考以下文章
为啥在另一个快照隔离事务中插入具有引用行的外键引用行的行会导致事务挂起?
我可以从 SqlConnection 对象中获取对挂起事务的引用吗?
假设分配给命令的连接位于本地挂起事务中,ExecuteReader 要求命令拥有事务。命令的 Transaction 属性尚未初始化