綴Photo の勉強ノートに戻る
Flutter技術2026.06.19

写真だけ残って、綴りが消える — それを防ぐのが Drift のトランザクションだった

FlutterDriftSQLiteデータ保全綴Photo

「トランザクションって何で要るんだっけ」を、自分の言葉で腹落ちさせた学習メモです。

綴Photo は「写真に気持ちを綴る」アプリなので、1枚保存するときに DB の操作が2つ走ります。photos テーブルに写真を入れて、meanings(綴り)テーブルにその言葉を入れます。この2つを素朴に順番でやると、途中で失敗したときに困る状態が生まれます。そこを埋めるのがトランザクションだった。まとめておく。

2つの操作が、途中で失敗すると

順番に実行するだけだと、こうなり得ます。

置き場所。閉じても残る正は端末 SQLite の photos と meanings。端末 SQLite photos写真 1行が残る1回目の INSERT が既に確定閉じても残る端末 SQLite meanings行なし2回目の INSERT が失敗閉じても空のまま残る正は左の写真1行。綴りの行は無い。

制約違反・ストレージ不足・処理の途中でアプリが落ちるなど、2回目の INSERT が通らないことは起き得ます。「言葉を綴るためのアプリ」で、言葉のない写真だけが取り残されます。これは見た目には分かりにくい、想定していない中途半端な状態で、後から一覧やリレーションを辿ったときに効いてきます。

ひとまとまりに包む

写真と綴りの INSERT を、同じトランザクションの中に入れます。

dart
// 写真 + 綴り を1つのトランザクションで保存する
await transaction(() async {
  final photoId = await _insertPhoto(...);   // 写真を INSERT
  await _insertMeaning(photoId, ...);        // 綴りを INSERT
});
置き場所。閉じても残る正は端末 SQLite の photos と meanings。未確定の行は確定するまで保存しない。綴りの INSERT が失敗塊ごと巻き戻る端末 SQLite photos行なし端末 SQLite meanings行なし両方成功塊ごと確定する端末 SQLite photos写真 1行が残る端末 SQLite meanings綴り 1行が残る閉じても残る正は右の2表。左は開始時点に戻る。

学びポイント

  • ユーザーから見た「1回の保存」が、内部では複数の INSERT に分かれることがあります。そういう時はトランザクションで原子性を担保します
  • 写真(親)だけ残って綴り(子)がない行は、その場では気づきにくく、後から一覧・集計で写真と綴りをつないで辿ろうとしたときに効いてきます。最初から作らないのが一番安いです
  • 「全部成功か、全部失敗か」をコードで保証できると、途中失敗の場合分けを自分で抱えなくて済みます

おわりに

トランザクションは名前だけ知っていて、「DBの安全機能」くらいの解像度で止まっていた。でも綴Photo の「写真+綴り=1セット」という具体に当てはめたら、何を守っているのかがはっきりした。守っているのは速さでも便利さでもなく、「綴りのない写真」みたいな中途半端な状態を存在させないことだった。


この記事は2026年6月時点の自分の理解で書いています。仕様や認識が変わってる可能性があります。