まだデータベースを触りだして2年目くらいの話です。とても厳しい先輩の下でDBAをやっていたときの経験と、そこから得た教訓となります。特に若い人たちに読んでいただけると幸いです。
背景
ある日、急なDBメンテナンスを依頼されました。日中はオンライン業務が稼働しているためメンテナンス作業は夜間の実施となります。作業内容としては、
- 特定レコードの物理削除
- ALTER文によるカラム追加
- etc…
という、予め準備をしておけばさほど難しくないものでした。なので、事前にSQLを作成して検証環境で動作を確認した上で、自分としては満を持して夜間の本番環境でのメンテナンス作業に臨みました。
まず、「特定レコードの物理削除」のため対象のテーブルに対してDELETE文を発行します。
-- テーブル名、カラム名、条件指定の値は実際のものとは異なります DELETE FROM table_A WHERE id = 1001 ;
ここで、SQLクライアントソフトを利用して
DELETE FROM table_A
のテキストを選択状態(ハイライトされた状態)で実行ボタンを押してしまったのです・・・。(SQLクライアントソフトにもよりますが)この場合、選択されたテキストのみが実行すべきSQLとして解釈されますので、つまりtable_Aのレコードを全件削除してしまったことになります。
とは言え、基本的に明示的にCOMMITしない限りはROLLBACKが可能な設定にしているので、この時点でリカバリ可能であることは自分で分かっていました。ですが、その後に取った行動が結果として事故を招いてしまいました。
発生した事故
ここで私が取った決断が、「table_Aのデータのリカバリよりも、その後に控えているテーブル定義変更の方が影響度が高い。この後の夜間バッチ処理もあるし、ROLLBACKでやり直すよりも先に後続作業を終えてしまおう!」と考えて先に進めてしまったのでした。データベースに対してある程度見識をお持ちの方であればここまで読んで察しが付いたのではないかと思いますが、データベースによってはALTER文やCREATE文などのDDLを実行するとそれまでの更新系SQLのDML操作が暗黙的にコミットされてしまいます(当時使っていたDBMSも暗黙コミットが発生する製品でした)。知識として知ってはいたので改めて冷静になって考えれば安直な行動をしていたことが分かりますが、まだ駆け出しのDBAであった自分にはこの状況下で冷静な判断ができなかったのだと思います。
報告と復旧
駆け出しのDBAでしたので、まずは経緯をしっかりと整理して、怖くて厳しい先輩に怒られることを覚悟の上で報告しました。先輩からは、
- まずはバッチ処理を開始する前にtable_Aのレコードをリカバリする必要がある
- バッチ処理の開始を保留してほしいことをバッチ処理監視の運用担当者に伝えること
- リカバリ作業は自分(先輩)がやるので、横で作業を見て手順を把握するように
という指示をいただきました。意外にも怒られはしませんでした。目は怖かったですけど・・・。
その後、先輩にリカバリ作業(バックアップからのリストア、ログを利用したPITR)を実施してもらい、無事にtable_Aをあるべき状態にすることができましたが、結果としてバッチ処理の開始が遅れたことでその終了も遅れてしまい、翌朝のオンライン開始が遅延してしまいました。先輩は私の代わりにお客様に説明と謝罪をし、事なきを得ました。
再発防止策
先輩から、事故が起こらないメンテナンス作業の仕組み化を考えるように言われました。SQLクライアントソフトを使って本番環境の更新操作をすることはあまり望ましくないので、
- 作業をスクリプト化する
- 更新前に、簡単にリカバリできるように更新対象テーブルのコピーテーブル作成をスクリプト冒頭に組み込む
- DELETE/UPDATE 前に同じ WHERE 句で SELECT COUNT(*) を実行し件数を確認する
- 更新系は必ず明示的に BEGIN → 影響行数を確認 → COMMIT
という対策をするようにしました。直接作業をする機会は少なくなりましたが、今でも基本的にこの手順に則るようにしています。
上司になった今、思うこと
しばらくしてからお酒の席で先輩に「いつも怖いのになぜあの時怒らなかったんですか?」と大胆なことをお尋ねしてみました。先輩からは、
- 事故発覚後にしっかり情報を整理して適切に報告していた
- 急な作業を依頼したのは自分(先輩)であり、いやな顔一つせずに引き受けてしっかり準備もしてくれたにも関わらず、後輩の作業ミスを叱るのは違うと思う
- 後輩の作業ミスは自分の責任であり、お客様への説明・謝罪は当然自分の義務である
- 事故を受けてしっかりと対策を考えていた
と答えていただきました。
今、自分にはDBメンテナンスなどの作業を任せている部下がいます。そしてたぶん、怖いと思われています(笑)。ただ、あの時の先輩のように、常日頃の要求は厳しくともいざという時に助けてあげなければいけない、責任を取ってあげなければいけないです。そしていつか自分の部下たちが新しい世代の部下を持つときに同じ行動ができるように育成していくことが上司の責任であると考えています。
おわりに
KENTEMでは、様々な拠点でエンジニアを大募集しています! 建設×ITにご興味頂いた方は、是非下記のリンクからご応募ください。 recruit.kentem.jp career.kentem.jp