運用データを安全に変える
目標
顧客企業が文章で送ってきた変更依頼を条件に絞り込み、元に戻す手段を用意し、コピー上で元に戻す操作を実演したうえで、本適用と対照群の検証まで一通り終えられるようになります。
なぜ重要なのか
前のコースで手にしていた権限は、事実上読み取りだけでした。間違った照会はやり直せばよく、間違った仮説は消して立て直せば済みます。書き込みは違います。間違ったUPDATEは、元に戻す手段をあらかじめ用意した分しか元に戻りません。
このラボが強制する4つのことは、すべて現場の規則です。依頼の文章を条件に置き換える前に数えます。依頼した人が描いた範囲と実際に変わる範囲はずれ、その幅は数えてみるまでどちらにもわかりません。元に戻す手段を先に作ります。ファイルコピーは丸ごと元に戻すためのもので、行スナップショットは何がどう変わったかを説明するためのものなので、両方が必要です。元に戻す操作を口約束にしません。元に戻す操作が失敗する理由はたいてい些細ですが、その些細な失敗を本適用のあとで見つけると、そのときはもう些細ではありません。変わってはいけないものも一緒に数えます。対照群のない検証は、隣を触ってしまった事故でも通ってしまいます。
今回の依頼はこうです。顧客企業の運用担当者が、精算の締めを理由に「pendingの注文をすべてcancelledに変更してください」と送ってきました。基準日は2026-08-29です。ところが、pendingの45件は1つのかたまりではありません。長く止まっているものもあれば、昨日入ってまだ処理中かもしれないものもあり、顧客が誰なのか確認できないものもあります。
このラボで絞り込む基準は2つです。作成日が2026-08-15より前であること(その日は含みません)、そしてその注文のcustomer_idがcustomersテーブルにあることです。
ステップ
/root/changeを作成し、/opt/data/support.sqlを/root/change/ops.dbに読み込んでください。顧客の原本ではなく、作業用コピーの上で始めます。/root/change/scope.txtに4行書いてください。request_total=は依頼どおりに置き換えたときに変わるpending全体、target=は上の2つの基準で絞り込んだ件数、excluded_recent=は作成日が2026-08-15以降のpending、excluded_orphan=はcustomersにいない顧客の古いpendingです。/root/change/ops.db.bakにファイルコピーを作り、/root/change/backup.csvに対象行の変更前の値をid,customer_id,amount,status,created_atのヘッダー付きで書き出してください。/root/change/plan.mdに計画書を書いてください。## 요청,## 대상과 범위,## 영향,## 되돌리는 방법,## 검증 방법,## 중단 기준(6つの節の名前は、韓国語で順に「依頼」「対象と範囲」「影響」「元に戻す方法」「検証方法」「中止基準」を意味する語です)の6つの節が必要で、## 대상과 범위が## 되돌리는 방법より前に来る必要があります。- トランザクション内でUPDATEを実行して
SELECT changes()を読み、ROLLBACKしてください。/root/change/dryrun.txtにchanges=と、ロールバック後にもう一度数えたafter_rollback_pending=を書きます。 /root/change/rehearsal.dbをops.db.bakから作って同じ変更を適用し、backup.csvで復元してください。/root/change/rehearsal.txtにapplied=、restored_pending=、そして復元結果とops.db.bakを行単位で比較したdiff=を書きます。- 同じ条件で
ops.dbに本適用を行い、/root/change/applied.txtにchanged=を残してください。 /root/change/verify.txtにbackup_ids_cancelled=、control_pending=、paid_unchanged=、refunded_unchanged=の4行を書き、plan.mdの末尾に## 적용 결과(韓国語で「適用結果」を意味する語です)の節を追記して、検証した数字を残してください。
参考
sqlite3 -readonly <파일> "<쿼리>"で読み取ると、誤って書き込む事故を防げます(プレースホルダーはファイル名とクエリです)。- 複数の文を1つのトランザクションにまとめるには、標準入力で渡してください(
sqlite3 ops.db <<'SQL' ... SQL)。 - 行単位の比較は、
ATTACHで2つのDBを接続してからEXCEPTで数えます。 - よくあるミス1: ステップ2で
excluded_recentとexcluded_orphanを合算して数えてしまいます。除外理由が違うなら別々に数えないと、計画書に理由を書けません。 - よくあるミス2: ステップ5でROLLBACKを忘れてCOMMITまで進んでしまいます。そうするとドライランが本適用になります。
- よくあるミス3: ステップ6の復元を、UPDATE文を新しく書いて行ってしまいます。本当の事故で手元に残るのはバックアップファイルだけなので、そのファイルだけで元に戻るかを確認する必要があります。
作業用コピーを作る
/root/changeを作成し、/opt/data/support.sqlを/root/change/ops.dbに読み込んでください。顧客の原本ではなく、作業用コピーの上で始めます。
顧客から受け取ったスナップショットは/opt/data/support.sqlです。sqlite3はSQLを標準入力で受け取ります。引数で渡すと、空のDBだけが残ります。
依頼と実際の範囲の差を数える
/root/change/scope.txtに4行書いてください。request_total=は依頼どおりに置き換えたときに変わるpending全体、target=は上の2つの基準で絞り込んだ件数、excluded_recent=は作成日が2026-08-15以降のpending、excluded_orphan=はcustomersにいない顧客の古いpendingです。
依頼どおりに置き換えた条件と、絞り込んだ条件を、それぞれCOUNTで数えてください。絞り込む基準は2つです。作成日と、その顧客がcustomersにいるかどうかです。
元に戻せる状態を作る
/root/change/ops.db.bakにファイルコピーを作り、/root/change/backup.csvに対象行の変更前の値をid,customer_id,amount,status,created_atのヘッダー付きで書き出してください。
ファイルコピーはcpで、行スナップショットはsqlite3の.mode csvで取ります。スナップショットの条件は、ステップ2で絞り込んだ条件と同じでなければなりません。
変更計画書を書く
/root/change/plan.mdに計画書を書いてください。## 요청, ## 대상과 범위, ## 영향, ## 되돌리는 방법, ## 검증 방법, ## 중단 기준(6つの節の名前は、韓国語で順に「依頼」「対象と範囲」「影響」「元に戻す方法」「検証方法」「中止基準」を意味する語です)の6つの節が必要で、## 대상과 범위が## 되돌리는 방법より前に来る必要があります。
6つの節が必要です。「元に戻す方法」の節には、何で元に戻すのかをファイルパスまで書く必要があり、「中止基準」の節は、どんな結果を見たら止めるかを書く場所です。
コミットせずにドライランする
トランザクション内でUPDATEを実行してSELECT changes()を読み、ROLLBACKしてください。/root/change/dryrun.txtにchanges=と、ロールバック後にもう一度数えたafter_rollback_pending=を書きます。
BEGINで開き、UPDATEしたあと、SELECT changes()で影響を受けた行数を読み、ROLLBACKで閉じます。ロールバックしたと書くことと、ロールバックされたことは別の事実なので、もう一度数えてください。
元に戻す操作をリハーサルする
/root/change/rehearsal.dbをops.db.bakから作って同じ変更を適用し、backup.csvで復元してください。/root/change/rehearsal.txtにapplied=、restored_pending=、そして復元結果とops.db.bakを行単位で比較したdiff=を書きます。
運用中のコピーではなく、別のコピーで行います。元に戻すときは条件を組み直さず、backup.csvを読んで戻してください。本当の事故で手元にあるのは、そのファイルだけです。
絞り込んだ条件で本適用する
同じ条件でops.dbに本適用を行い、/root/change/applied.txtにchanged=を残してください。
ステップ5で試した条件と、文字どおり同じ条件を使います。ここで条件を手直ししたくなったら、ドライランをやり直す必要があるという意味です。
対照群まで数えて確認する
/root/change/verify.txtにbackup_ids_cancelled=、control_pending=、paid_unchanged=、refunded_unchanged=の4行を書き、plan.mdの末尾に## 적용 결과(韓国語で「適用結果」を意味する語です)の節を追記して、検証した数字を残してください。
変わるべきものと、変わってはいけないものを、一緒に数えます。そして計画書は、結果を書いて初めて閉じます。「適用結果」の節を追記してください。