bsddb3 DB.get/put зависает с транзакцией
Я довольно новичок в Berkeley DB, и я пытаюсь использовать его в Python с bsddb3 с транзакциями для обеспечения энергопотребления с DB_AUTO_COMMIT и без аргументов транзакции, чтение и запись работают нормально. Но в тот момент, когда я вызываю get/put с ручной транзакцией, вызов зависает на неопределенное время, практически без использования ЦП (около 50 Кбит / с) и без дискового ввода-вывода.
_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, а после него - при вызове len для объекта базы данных, выполняемого графическим интерфейсом отладчика после завершения вызова get/put (а также периодически, если программа выполняется свободно). Это, очевидно, застревает в цикле получения ресурсов, который никогда не завершается, потому что транзакция выполняется (у меня нет символов для сборки bsddb3 - который статически связан с BDB, не меньше), поэтому я не заинтересован в том, чтобы тратить время, чтобы выяснить, что такое дюжина или около того функций в стеке вызовов под вызовом DB_length). Вероятно, это также связано с тем, что время отклика на любые команды отладчика увеличилось до примерно 5 секунд (когда оно не заблокировано), когда я представил bsddb3 в проекте.
Подводя итог, можно сказать, что это ядовитое взаимодействие между графическим интерфейсом отладчика, пытающимся поддерживать актуальность окна своих переменных, и проектным решением о том, что базы данных bsddb3 должны быть отображениями. Я очень открыт для предложений, как обойти это; Я попробовал несколько вещей, но не смог выяснить, как удалить метод len из объектов DB (это свойство только для чтения, так как оно реализовано в C). Прямо сейчас я создаю обертку вокруг БД, которая НЕ является последовательностью; это решает проблему, если вы случайно не наведете курсор мыши на объект БД и отладчик не попытается извлечь его свойства.