Windows10で、2018年春のアップデートが行われた。
ありがちだが、バグはいろいろあるようだ。
そしてうちでも、そのバグに悩まされることになった。
WSLだ。
https://gist.github.com/hirokuma/4ea889b2a596c59ef4f862e9df54e469
lmdbのmdb_put()がうまく処理できないようなのだ。
MDB_BAD_TXN: Transaction must abort, has a child, or is invalid
最初はmdb_get_cursor()を使って失敗していたのでcursor関連かと思い込んでいたのだが、どうもMDB_txnのチェックでエラーになっているようだ。
そして、DBファイルを残したままであれば、test1()を実行しなければ発生しない。
test1()のmdb_put()をコメントアウトするだけでも大丈夫そうだ。
MDB_txnは毎回MDB_envから取ってきているので、MDB_envに何か残っているということか・・・。
mdb_env_sync()というAPIがあった。
http://www.lmdb.tech/doc/group__mdb.html#ga85e61f05aa68b520cc6c3b981dba5037
何か残っているというならば、ファイルシステムへの書き込みができていないとかだろう。
ただ、ライトキャッシュが吐き出されていなかったとしても、再起動しているわけでも無い状態でOS経由で読み込む分にはキャッシュから読み込んでくれないといかんはずだ。
じゃないと、単に「書込みをしなかった」のと同じになってしまうではないか。。。
ひとまず、test1()とtest2()の間に、以下を追加した。
mdb_env_sync(env, 1);
そして、DBファイルを削除して実行すると・・・動いた。
じゃあ、mdb_env_sync()せずに、コマンドでsyncを実行したらうまく行くのでは?と思ったが、そうでもなかった。
が、syncせずとも、LMDBサンプルを一度実行して失敗した後、5~10秒くらい待ってからもう一度実行すると成功した。
なんじゃそりゃー
そんな感じで、一時的に回避したいなら、強制的に吐き出させるしかなさそうだ。
まいったなぁ。
そして、mdb_env_sync()をmdb_txn_commit()後に行うようにしてみたのだが、作ったサンプル程度であれば動いたのだが、作業でやってるアプリだとダメだった。。。
サンプルでダメだったときはmdb_get()なんかで発生していたのだが、私のアプリだとmdb_txn_commit()で起きてしまう。
MDB_TXN_FINISHEDかMDB_TXN_ERRORが原因のようだが、ファイルの書き込みが疑わしいとなってしまうと、DBとしては何が正しいのかわからんので、WSLが原因なのか、私の実装が悪いのかは、今回の現象が直ってからだな。
こちらも1803から起きているという報告のようだ。
返信削除cache coherencyと書いてあるから、キャッシュか。
https://rchain.atlassian.net/browse/CORE-637?focusedCommentId=11512&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-11512