Slide 1

Slide 1 text

2025年6月28日 PHP Conference Japan 2025 さかうぇ(@sakawe_ee) システム成長を止めない! 本番無停止テーブル移行の全貌

Slide 2

Slide 2 text

2 新潟生まれ、新潟育ち。.NET → TypeScript → PHP SIerで東京暮らし約10年、Uターン後、2024年3月 コドモン入社 以来、新潟からフルリモート勤務 & PHPデビュー 請求系ドメイン担当チームで開発・運用保守に携わっている。 自己紹介 さかうぇ ひかる 経歴 そろそろ運転の練習をしてペーパードライバーを卒業したい… 最近の気になり @sakawe_ee

Slide 3

Slide 3 text

3 パパママと、子どもとの時間に 1秒でも多くの笑顔と愛情を すべての先生に 子どもと向き合う時間と心のゆとりを 「保育・子育て」と 社会をつなげる 保護者の子育てへの伴走 保育・教育者の環境改善 子育ての社会インフラ作り 子どもを取り巻く環境を テクノロジーの力で よりよいものに ミッション 私たちの使命

Slide 4

Slide 4 text

すべての先生に 子どもと向き合う 時間と心のゆとりを こんなプロダクトを開発しています メインプロダクトは、こども施設職員の業務を支援するWebアプリケーション。 保護者と施設のやり取りを支えるモバイルアプリケーションや、施設職員向けモバイル版 アプリケーション、外部サービスと連携するAPIなども開発しています。 4

Slide 5

Slide 5 text

5

Slide 6

Slide 6 text

6 背景

Slide 7

Slide 7 text

7 打刻テーブルのユースケース ユーザーは保護者の方、子ども、職員の方々 ● 朝、職員が出勤時に打刻する ● 朝、保護者が登園時に打刻する ● 朝、施設と保護者向けに登園済チェックをする ● 夕方、保護者がお迎えで打刻する ● 夕方、小学生が学童で退室打刻する ● 職員が入室時刻を一括入力する ● 職員が誤入力を修正する ● 夜、職員が退勤時に打刻する

Slide 8

Slide 8 text

8 打刻テーブルのデータが10億件に到達しそう! 2015年から溜まっている打刻データが 2025年秋には10億件に到達しそう! テーブルの構造変更やデータの移行などができなくなるリスクが…! ➡ 何かしらの対処が急務!しかし…

Slide 9

Slide 9 text

9 既存テーブルの課題 責務の異なるデータが混在している:効率が悪い ● 子どもの打刻データ(入退室打刻) ○ 子どもの入室/退室通知のステータス ● 職員の打刻データ(出退勤打刻) 毎日100万件ずつ増えていくのにシステム停止できない ● 朝は6時台から、夜は23時台まで ● 休日保育もあるため土日もシステム停止できない

Slide 10

Slide 10 text

10 打刻データの制約 データ保持の制約 ● 施設は監査の都合で 10年間は保持 & 5年間は修正できる必要がある 変更容易性の確保 ● いつでもテーブルの構造変更ができる状態にしたい ● 保持期間を過ぎたらさくっと削除したい (データ量の影響を受けたくない)

Slide 11

Slide 11 text

11 打刻データの特性 ほぼ毎日利用されている ● 朝は6時台から、夜は23時台まで ● 休日保育もあるため土日も ● 利用できない場合の代替手段が "紙" ピークタイム ● 朝7:30〜9:00に一番スパイクするピークタイム ● 夕方も朝ほどではないが山ができる

Slide 12

Slide 12 text

12 チームの状況 現実的な話 ● 入退室データを活用したいという案件がちょこちょこ発生する ➡テーブル分割と案件のどちらかしか進められない状態は避けたい ● 優先度の変化を柔軟に受け入れられる状態を保ちたい もっとシビアな話 ● ほぼ毎日利用されているため、 長時間システム停止してリリースできるタイミングがほぼ無い

Slide 13

Slide 13 text

13 CONFIDENTIAL - © 2022 CoDMON Inc. 13 システム成長を止めない! プロダクト開発部の基本方針 ● 小さく進める、リリースは少しずつ流れ続ける ○ from エクストリームプログラミングの原則 ● 改修は毎日のリリースフローの中で進める ○ 極力、夜間対応はしない ○ 仮に計画停止しても 夜22時〜朝6時の 約8時間まで ● できるなら改善も成長もどちらもやっていく!が基本姿勢

Slide 14

Slide 14 text

14 CONFIDENTIAL - © 2022 CoDMON Inc. 14 今日の話 "リリースを小さく"とは聞くけれど、勘所が掴めないあなたに 毎日稼働しているシステムでも、影響を抑えて成長させたいあなたに 保管し続けなければいけない大量データに悩んでいるあなたに ベイビーステップで、ユーザー影響無く 内側のテーブルをすげ替える試み の全貌をお話しします

Slide 15

Slide 15 text

15 目次 ● テーブル分割方針 ❏ パーティションテーブルの採用 ● 更新系の修正とデータ移行のハイライト ● 参照先テーブル切り替えの進め方 ● まとめ ❏ "リリースを小さく"とは? 更新系 修正 参照先 切り替え 方針決め

Slide 16

Slide 16 text

16 テーブル分割方法の選択肢 更新系 修正 参照先 切り替え 方針決め

Slide 17

Slide 17 text

17 (補足)システム構成(かなり省略版)

Slide 18

Slide 18 text

18 (補足)パーティションテーブルとは ● 1つのテーブルを論理的に分ける、データベースのしくみ ● パーティションを指定して一括削除、別テーブルへの移動も可能 (しかも早い) 6月をupdate 5月をselect 8月をselect 6月をupdate 5月をselect 8月をselect 非パーティションテーブル パーティションテーブル 5月 6月 8月

Slide 19

Slide 19 text

19 テーブル分割方法の選択肢 ●A.物理テーブルに分割する メリット ・テーブルメンテナンスを並列で実行可能 デメリット ・日付をキーにテーブルを切り替える  対応が必要 ・テーブルをまたがる検索の場合は結果を  マージする必要がある ・定期メンテナンスの負荷が大きい ●B.パーティションテーブルの採用 メリット ・現状の仕組みのままデータ参照可能 ・定期的なメンテナンスの負荷が低い ・不具合やミスが起こりにくい  (DBの仕組みを使うためリスク低) デメリット ・レコード数に応じて特定操作を行った際  のメンテナンスの時間が長くなる ・コドモンで運用実績がない

Slide 20

Slide 20 text

20 テーブル分割方法の選択肢 ●A.物理テーブルに分割する メリット ・テーブルメンテナンスを並列で実行可能 デメリット ・日付をキーにテーブルを切り替える  対応が必要 ・テーブルをまたがる検索の場合は結果を  マージする必要がある ・定期メンテナンスの負荷が大きい ●B.パーティションテーブルの採用 メリット ・現状の仕組みのままデータ参照可能 ・定期的なメンテナンスの負荷が低い ・不具合やミスが起こりにくい  (DBの仕組みを使うためリスク低) デメリット ・レコード数に応じて特定操作を行った際  のメンテナンスの時間が長くなる ・コドモンで運用実績がない 決定

Slide 21

Slide 21 text

21 (補足)他の選択肢 この制約がなければ他の選択肢もあった データ保持の制約 ● 施設は監査の都合で 10年間は保持 & 5年間は修正できる必要がある ● 期間を過ぎたら(データ量の影響を受けずに)さくっと削除したい

Slide 22

Slide 22 text

22 テーブル分割の方針 更新系 修正 参照先 切り替え 方針決め

Slide 23

Slide 23 text

23 やること 1) パーティションテーブル化する 2) テーブルを責務に合わせて分割する ● 入退室打刻データ(子どもの打刻データ) ● 入退室通知ステータス(子どもの打刻通知用のデータ) ● 出退勤打刻データ(職員の打刻データ) ➡ 新テーブルを作成してデータを移行し、参照先を切り替える

Slide 24

Slide 24 text

24 CONFIDENTIAL - © 2022 CoDMON Inc. 24 "システム成長を止めない"ために? 常にリスクを下げる選択をする ● いきなり切り替えない ● いつでも変更前に戻せるようにしておく ➡フィーチャートグル ● 必要に応じて検証期間を挟む ● ユーザー影響が少ない環境・機能からリリースする コドモン コドモングリーン ph.1 出退勤データ 9,400万件 25万件 ph.2 入退室データ 7億4,000万件 1,800万件 ① ② ③ ④

Slide 25

Slide 25 text

25 進め方 1) 新テーブルを作成 ○ 責務分割済みのパーティションテーブル

Slide 26

Slide 26 text

26 進め方 1) 新テーブルを作成 ○ 責務分割済みのパーティションテーブル 2) 更新系機能の更新先テーブルを変更 ○ 現行・新テーブルの両方同時に書き込むように アプリケーションを変更する

Slide 27

Slide 27 text

27 進め方 1) 新テーブルを作成 ○ 責務分割済みのパーティションテーブル 2) 更新系機能の更新先テーブルを変更 ○ 現行・新テーブルの両方同時に書き込むように アプリケーションを変更する 3) 過去データを新テーブルに移行 ○ 現行テーブル・新テーブルに同じデータがある状態にする

Slide 28

Slide 28 text

28 進め方 1) 新テーブルを作成 ○ 責務分割済みのパーティションテーブル 2) 更新系機能の更新先テーブルを変更 ○ 現行・新テーブルの両方同時に書き込むように アプリケーションを変更する 3) 過去データを新テーブルに移行 ○ 現行テーブル・新テーブルに同じデータがある状態にする 4) 参照系機能の参照先テーブルを変更

Slide 29

Slide 29 text

29 更新系機能の変更 & データ移行の流れ 出退勤機能に先に着手し、データ移行中にもう一方に着手するイメージ 同時更新 実装 出退勤機能 データ移行 参照先 切り替え 同時更新 停止 入退室機能 同時更新 実装 データ移行 参照先切り替え 同時更新 停止

Slide 30

Slide 30 text

30 更新系の修正とデータ移行のハイライト 更新系 修正 参照先 切り替え 方針決め

Slide 31

Slide 31 text

31 現行・新テーブル同時書き込みとデータ移行を開始🚀 出退勤までは順調 ● 出退勤は順調に同時書き込み処理の追加とデータ移行が完了 ● 入退室データの同時書き込み追加に着手 重複データが日常的に発生していることに気づく ● 重複データの考慮を追加して出退勤の書き込み処理を修正 出退勤データを再移行! ● 移行結果検証の結果、出退勤データの移行は完了🎉 ● 入退室の書き込み処理にも展開

Slide 32

Slide 32 text

32 入退室データも出退勤データと同じように移行が… 夕方のピークは耐えた…… 朝のピークタイムにDB更新の遅延が発生 ● すぐにフィーチャートグルを書き換え、同時書き込み停止 ○ つまり、移行できず 朝のピークタイムに発生する多重打刻に耐えられなかった ● 改めて調査 → 既存のクエリ発行の仕組みがいまいち ➡ クエリを多重打刻に対して 最適化

Slide 33

Slide 33 text

33 念のため、同時書き込み処理だけをカナリアリリース ● 影響を抑えつつ対処の妥当性を検証 ○ 引き続き、フィーチャートグルですぐ停止できる状態 ● 重複データが発生しても値が一致することを確認 ● 今度こそ 現行テーブルと新テーブルに同じ値が書き込まれるはず! そして、改めて入退室データ移行! ● 移行結果検証の結果は、問題なし ➡ 入退室データの移行も完了! 同じ轍は踏みたくない!入退室データの移行検証

Slide 34

Slide 34 text

同時書き込みのリリースが完了🎉 現行テーブルと新テーブルに同じデータがある状態に!

Slide 35

Slide 35 text

35 参照先テーブル切り替えの進め方 更新系 修正 参照先 切り替え 方針決め

Slide 36

Slide 36 text

36 "ベイビーステップでリリースする"とは? ウォーターフォール的な流れ ● がっつり対象機能調査 ● テスト計画 ● プログラム修正 ● がっつりテスト実施 ● リリース計画 ● 本番リリース 要件定義 設計 開発 テスト リリース

Slide 37

Slide 37 text

37 "ベイビーステップでリリースする"とは? アジャイルな流れ ● 対象機能調査 ● 開発(テスト&実装) ● リリース これを繰り返して少しずつ理想の状態に近づけていく 出典:https://udemy.benesse.co.jp/development/system/agile.html

Slide 38

Slide 38 text

38 参照先テーブル切り替えの進め方 対象機能は 30個超え! ● 全てに細かい検索パターンのテストを追加するのは時間がかかる ➡ 工数をかけずにリスクを回避したい! テーブル移行前後でデータの内容は同じ ● DBから取得した結果が同じなら 正しく動作していると言えるのでは…?🤔 対象機能調査結果

Slide 39

Slide 39 text

39 参照先テーブル切り替えの進め方 比較検証期間を設けて細く長く切り替えていこう! ● テストはハッピーパスのみ ● 動いているものの中で検証する ○ 現行テーブルと新テーブルの両方からデータ取得 ○ 結果セットを比較して不一致の場合にログ出力 ※ パフォーマンス影響を考慮して件数が少ない場合のみ アプリ上は現行データを返している ➡ ユーザー影響なし

Slide 40

Slide 40 text

40 参照先テーブル切り替えの進め方 こうして、検証完了した機能から参照先テーブルを切り替えていった もちろん、いつでも参照先を切り戻せる状態でリリース フィーチャートグルを活用

Slide 41

Slide 41 text

CONFIDENTIAL - © 2025 CoDMON Inc. 参照先切り替え、安定して稼働中 出退勤データは完了済み🎉 入退室データは鋭意継続中🏃 to be continued...

Slide 42

Slide 42 text

42 まとめ

Slide 43

Slide 43 text

"リリースを小さく"?

Slide 44

Slide 44 text

44 実際、どんな単位でリリースしていたのか 頻度 ● ICTコドモンのリリースワークフローは月・金1回、火〜木2回 ● 最大で週8回リリースできる ● "コドモンレコ"も同じ考え方 曜日 月 火 水 木 金 午前 ー リリース リリース リリース リリース 午後 リリース リリース リリース リリース ー

Slide 45

Slide 45 text

45 実際のIssue=リリース単位

Slide 46

Slide 46 text

46 実際のIssue=リリース単位 完了済みだけでこんな感じ ● 入退室の参照切り替えのIssueがさらに 30 × 3 = 90 追加の見込み

Slide 47

Slide 47 text

47 実際、どんな単位でリリースしていたのか 例 ● 登降園のdriver差し込み ● 登降園の 重複データのテスト追加 ● 出退勤の更新ロック対応 ● トランザクションを入れる ● 出退勤一覧画面APIのテスト追加 ● 出退勤一覧画面APIのデータ比較検証追加 ● 出退勤一覧画面APIの参照先テーブルを切り替える メソッドアウトするだけ テスト足しただけ(影響なし) 制御入れただけ テスト足しただけ(影響なし) 検証するだけ 分岐するだけ

Slide 48

Slide 48 text

48 ほぼ毎日リリース ● GitHub の contributions も増えました ● 半年間 で 約1年分の contributions 実績 【通常モード】 【テーブル分割集中期間】 マージ ≒ リリース

Slide 49

Slide 49 text

49 CONFIDENTIAL - © 2022 CoDMON Inc. 49 "リリースを小さく"とは? 一気に作りきらない ● メソッドアウトするだけ ● テストを追加するだけ 修正の前にログを活用して検証してもよい ● パラメータ追加しようとしている値が取れているか検出するだけ ● それは使われているブロックなのか検証するだけ 細く長く変更していくという選択肢 ● このテーブル分割・移行作業も主に2名で進めてきた フィーチャートグルを活用

Slide 50

Slide 50 text

50 (本当はこういうやり方もしたかった…) ● 本番と同じトラフィックが流れる環境でテスト ● 朝と夕方のピークをいつでも再現できる検証環境 ○ 負荷検証環境はあるが、再現できていない ● 最後まで全速力で走り切りたかった…

Slide 51

Slide 51 text

51 やりたいことも課題もまだまだあります!

Slide 52

Slide 52 text

52 コドモン採用ページ 開発ブログ コドモンでは一緒に働きたい仲間を募集しています!

Slide 53

Slide 53 text

53 ご清聴ありがとうございました!

Slide 54

Slide 54 text

No content