最近対応した不具合で勉強になったのでメモ
#不具合内容
ActiveAndroidからSQLiteを利用してるアプリのデータ引き継ぎで、dbファイルをやりとりしても正常に引き継がれなかった。
#原因
SQLiteのジャーナルモードがwalになっており、本体dbファイルが更新されていなかったため。
#ジャーナルモードとは??
http://nave-kazu.hatenablog.com/entry/2015/12/18/140634
SQLiteのデータ更新時の挙動を変えるもの。
トランザクションを貼る=>コミットするまでのデータをどこに保持するかという話。
ジャーナルモードの例を下記に2点挙げる。だいたいこの二つのどっちかを使ってる印象がある。
https://sqlite-r.com/journal_mode
によれば他にもいろいろモードがあるので、状況に合わせて使い分けるべき
####delete(デフォルト)
コミットまでの変更をdbファイル名末尾に-journal
がつく別ファイルをつくってそこに書き込む。
コミットされたら変更を本体dbファイルに反映して-journalの方を削除する。
####wal
トランザクション開始から終了までの更新内容を-shm
ファイルに書き込み、コミットした時に-wal
ファイルへ更新内容を書き込む。
よってdeleteモードと違い、コミットした段階では本体dbは更新されない。
本体が更新されるタイミングは下記の2通り
- コミット数が設定された定数を超えた場合
- 他にだれも接続していない状態でDBの接続を切った場合
#対応
ということでデータ引き継ぎの際本体dbファイルが更新されていないと、移行先でデータが合わないことになる。
解決策としては移行前に本体dbを更新させればよいので、dbファイルを送信する直前に
ActiveAndroid.dispose(); //一旦破棄すれば接続が切れてdbファイルに書き込まれる
を追加。その後initializeし直す
これで引き継ぎ成功した
#余談
要するに本体dbファイルを更新すればよいので、上記以外にもいい方法があるような気がする…
そもそも一度disposeしたらinitializeされることを絶対に保証する必要があるのでデバッグは慎重に行う。
それか、shmとwalもいっしょに移行してしまえばいいのだがそっちの方が面倒そう…