本文へ移動
技術を、自社の仕事に。
判断と実行を助けるメディア

記事を検索

MySQL 9.7のDATE挙動変更 — 数字だけが静かに変わる更新

目次 · 6項目

基幹システムの保守で、いちばん報告が遅れるのはこの形の不具合です。アプリケーションログにエラーは一件もない。処理は最後まで完走している。ただ、出てくる数字が先月と違う。

気づくのは開発側ではなく、たいてい数字を毎月見ている経理か営業の担当者です。「先週の曜日別の集計、日曜だけゼロになっていませんか」と聞かれて、そこから調査が始まります。原因を遡ると、2か月前のデータベースのバージョン更新に行き着く。この頃には、間違った数字で作った資料が何枚も社外に出ています。

MySQL 9.7 の DATE 型まわりの変更は、まさにこの種の更新にあたります。

何が変わったのか

MySQL 9.7 では、サーバー内部での DATE 値の扱いが作り直されました。従来は日付と時刻を共通の構造で持っていたところを、DATE 専用の表現に置き換えるリファクタリングが入っています。これに伴い、TIMEDIFF()FROM_DAYS()DAYNAME()ADDDATE() といった日付関数の周辺で複数の修正が行われました。

gihyo.jp の検証記事では、MySQL 8.4.11 と 9.7.2 を並べたときの差として DAYNAME() の例が挙げられています。DAYNAME() は本来「Sunday」のような曜日名の文字列を返す関数ですが、これを数値演算の中に入れた場合の結果が変わりました。

書き方MySQL 8.4.11MySQL 9.7.2
DAYNAME(日付) を数値として扱うWEEKDAY() 相当の値(日曜なら 6)0

8.4 系では曜日番号として使えてしまっていたものが、9.7 では文字列を数値に変換した結果である 0 になります。どちらが正しいかで言えば 9.7 の側が素直です。曜日番号が必要なら WEEKDAY() または DAYOFWEEK() を明示的に使い、曜日名の暗黙変換に依存しないようにします。

問題は、正しくなったこと自体ではありません。SELECT の数値演算では、処理を中断せず結果だけが変わる場合があるという点です。SQLは通り、行数も変わらず、集計結果だけが静かに変わります。

なぜ回帰テストをすり抜けるのか

多くの現場で用意されている自動テストは、この種の変更を捕まえられません。理由は3つあります。

判定が「落ちないこと」になっている。 バッチが正常終了したか、APIが200を返すか、を見ているテストは全部通ります。

件数でしか比較していない。 「1,000件処理された」は変わらないので、値の中身が変わったことに気づけません。

テストデータが薄い。 曜日ごとの分布を持たない数十件のフィクスチャでは、日曜だけがおかしいという症状が現れません。

3つ目は特に見落とされます。日付にまつわる不具合は、月末、うるう年、年度の境目、祝日といった「端」で出ます。テストデータを本番から抜いて作っている場合でも、抜き出した期間にその端が含まれていなければ、同じことです。

エラーがない更新も、値を比べる。更新前を記録、更新後と比較、業務で受け入れ判定を整理した図

つまり、例外が出る変更に強いテストは、値が変わる変更にはほぼ無力です。ここを分けて設計していないと、バージョン更新のたびに同じ見落とし方をします。

値の変化を捕まえる受け入れ確認

DBのメジャーバージョンを上げるときに追加すべきなのは、テストケースの数ではなく、比較の軸です。

1. 新旧を並走させて出力を突き合わせる

本番相当のデータを載せた旧バージョンと新バージョンを両方立て、主要な集計SQLを同じ入力で流して結果を丸ごと比較します。件数ではなく、値の全列を比べます。差分が出た箇所だけを人が見れば済むので、確認の総量は思ったより増えません。

2. 比較対象は「経営が見る数字」から選ぶ

全SQLを比べる必要はありません。月次で社外に出る帳票、請求金額、在庫数といった、間違えたときに取り返しがつかない出力を先に押さえます。この選定は開発側だけではできないため、発注側が「これが狂うと困る」というリストを出す工程が要ります。

3. 差分が出たときの扱いを事前に決めておく

差分には、仕様変更によるものだけでなく、順序の未指定や丸め方法によるものが混ざる場合があります。「差分が出たら止める」ではなく「差分の一覧を作り、1件ずつ判断して記録する」形にしておかないと、確認そのものが形骸化します。

この工程を見積もりに載せる方法は、テスト工数を掛け算2つで出す考え方で整理した通りです。比較対象の本数と、差分1件あたりの確認時間で見積もれます。

保守契約のどこに書いてあるか

技術的な話とは別に、契約側の確認も要ります。データベースのメジャーバージョン更新が、保守契約の範囲に入っているかどうかです。

よくあるのは、「セキュリティパッチの適用は保守範囲、メジャーバージョン更新は別途見積もり」という切り分けです。この場合、更新そのものは追加費用の作業になりますが、では更新後に値が変わっていないことの確認は誰の仕事なのか。ここが曖昧なまま作業だけ進むと、冒頭のように2か月後に発覚します。

保守契約でSLAと作業範囲をどう定義するかでも触れましたが、更新作業と受け入れ確認は別の項目として書き分けておくのが安全です。「更新した」ことの完了条件を、「起動した」ではなく「主要な出力に想定外の差分がないことを確認した」に置く、という書き方になります。

既存のスキーマに手を入れる場合は、テーブル設計そのものを見直す判断と合わせて検討したほうが、二度手間になりません。

もうひとつ決めておきたいのが、戻す条件です。更新後に想定外の差分が見つかったとき、旧バージョンへ戻すのか、差分を許容して前へ進むのか。判断は状況次第ですが、「どちらの選択肢も取れる状態を何日間維持するか」だけは事前に決められます。旧環境を止めるタイミングを作業当日に決めると、たいてい早すぎる側に倒れます。

次にやること

自社のシステムで、日付から曜日や期間を計算しているSQLがどこにあるかを洗い出してください。日付関数の戻り値を、そのまま計算や比較に使っている箇所が候補です。

洗い出しが終わったら、そのSQLの出力が毎月どこに届いているのかを確認します。社外に出る資料に届いているものがあれば、そこが受け入れ確認の第一候補になります。バージョンを上げる前に決めておけば、上げた後の作業は比較するだけです。

データベースのバージョン更新に伴う影響調査、既存システムの受け入れテスト設計、保守範囲の整理については、グリームハブの開発・AI・自動化のご相談で承っています。現行バージョンと処理の作りによって進め方が変わるため、お問い合わせから個別にご相談ください。

Sources

この記事を共有XFacebook
鈴木 翔

技術の可能性に魅了され、学生時代からプログラミングとデジタルアートの分野に深い関心を持つ

この記事のテーマを、自社の次の一歩へ

自社での進め方を、具体的に。

つくりたい仕組み、既存システム、運用の条件を整理し、実現に向けた次の一歩を考えます。

  • 実現したい仕組み
  • 既存環境との接続
  • 運用の条件
開発・運用の構想を相談する

構想段階からご相談いただけます。この記事の情報を相談フォームに引き継ぎます。

最新記事をメールで受け取る