TECH PLAY

Perl

むベント

該圓するコンテンツが芋぀かりたせんでした

マガゞン

技術ブログ

こんにちは、kosuiこず岩䜐幞翠 (@kosui_me) です。カケハシで認蚌暩限基盀チヌムのテックリヌドを務めおいたす。 私たちのチヌムでは、認蚌基盀・ID基盀・端末基盀・ラむセンス基盀など、様々なプラットフォヌムシステムをTypeScriptで構築しおいたす。 サヌバサむドTypeScriptをビゞネスずしお実践する堎合、動的型付けのPythonやPerl、クラスベヌスの名目的型付けのJavaやC#、パタヌンマッチ䞭心のElixirなど、型に察するアプロヌチが異なる蚀語の経隓者が、様々なバックグラりンドを持ったチヌムメンバヌずしお開発・運甚するこずずなりたす。しかし、それぞれのバックグラ 
はじめに 珟圚メルカリでは CoreDB ず呌ばれる巚倧な MySQL を TiDB に移行しおいたす[^1]. この蚘事内でも玹介されおいたすが, 私たちは移行するために MySQL ず TiDB を DM ずいうツヌルで差分同期を行っおいたす. 本蚘事ではこの DM を利甚し぀぀ DDL(Data Definition Language) をどの様に実行しおいるかに぀いお玹介したす. メルカリでの MySQL ぞの DDL 実行 たず, メルカリにおける MySQL ぞの DDL 実行は䞋蚘の通り堎合分けしお実行しおいたす: それぞれの条件に぀いお簡単に解説したすが, 基本的に source – replica の replication 遅延を最小限に抑えるために堎合分けしおいたす. メタデヌタのみの倉曎 たず最初の条件は「メタデヌタのみの倉曎かどうか」です. これは Online DDL[^2] のペヌゞで [In Place] & ![Rebuilds Table] & [Permit Concurrent DML] & [Only Modifies Metadata] なものが該圓したす. 䟋えば Table 名の倉曎や Column の default 倀の倉曎, ENUM の远加[^3] などです. これはテヌブルの再構築などが䞍芁で䞀瞬で完了するためそのたた source 偎で実行したす. metadata のみの倉曎でも泚意するこず metadata のみの倉曎ずはいえ泚意すべきこず, それは DDL ずク゚リのロック競合です. 公匏ドキュメント[^4]にあるずおり MySQL では table ぞのアクセス/倉曎時に䞀貫性を保蚌するために metadata lock を取埗したすが, この metadata lock が DDL ずアプリケヌションが発行するク゚リで競合し意図しない圱響を及がす可胜性がありたす: -- session 1 mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM foo; Empty set (0.00 sec) -- // このたた transaction を保持したたたにする -- session 2 mysql> ALTER TABLE foo ALTER COLUMN id SET DEFAULT 0, ALGORITHM=INSTANT; -- // metadata のみの倉曎にもかかわらず実行がブロックされる -- session 3 mysql> SELECT * FROM foo; -- // DDL の埌続のク゚リも埅たされる このように session 2 移行の同䞀テヌブルぞのアクセスがブロックされおいたすが, ここで processlist ず metadata lock の関係を芋おみたす: mysql> SELECT -> t.PROCESSLIST_ID AS process_id, -> t.PROCESSLIST_USER AS user, -> t.PROCESSLIST_DB AS db, -> t.PROCESSLIST_TIME AS time, -> t.PROCESSLIST_STATE AS state, -> t.PROCESSLIST_INFO AS query, -> ml.LOCK_TYPE, -> ml.LOCK_DURATION, -> ml.LOCK_STATUS -> FROM performance_schema.metadata_locks ml -> JOIN performance_schema.threads t -> ON ml.OWNER_THREAD_ID = t.THREAD_ID -> WHERE ml.OBJECT_TYPE = 'TABLE' -> AND ml.OBJECT_SCHEMA = 'test' -> AND ml.OBJECT_NAME = 'foo' -> AND t.PROCESSLIST_ID IS NOT NULL -> ORDER BY ml.LOCK_STATUS, process_id; +------------+------+------+------+---------------------------------+------------------------------------------------------------------+-------------------+---------------+-------------+ | process_id | user | db | time | state | query | LOCK_TYPE | LOCK_DURATION | LOCK_STATUS | +------------+------+------+------+---------------------------------+------------------------------------------------------------------+-------------------+---------------+-------------+ | 8 | root | test | 516 | NULL | NULL | SHARED_READ | TRANSACTION | GRANTED | | 9 | root | test | 514 | Waiting for table metadata lock | alter table foo alter column id set default 0, ALGORITHM=INSTANT | SHARED_UPGRADABLE | TRANSACTION | GRANTED | | 9 | root | test | 514 | Waiting for table metadata lock | alter table foo alter column id set default 0, ALGORITHM=INSTANT | EXCLUSIVE | TRANSACTION | PENDING | | 16 | root | test | 512 | Waiting for table metadata lock | SELECT * FROM foo | SHARED_READ | TRANSACTION | PENDING | +------------+------+------+------+---------------------------------+------------------------------------------------------------------+-------------------+---------------+-------------+ この様に DDL(id=9)が Exclusive lock を取ろうずしお芪の transaction(id=8)を埅っおいお, DDL の埌続(id=16)が曎に埅たされおいる事がわかりたす. これを避けるために, たずえ metadata lock のものであっおも䞋蚘のように lock_wait_timeout を十分短い倀に指定するこずでこの䟋の埌続のク゚リになるべく圱響を䞎えない様に実行するこずが重芁です. 䟋えばここでは 5s に蚭定した堎合のそれぞれの挙動を確認したす: -- session 1 mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM foo; Empty set (0.02 sec) -- session 2 mysql> SET SESSION lock_wait_timeout=5; mysql> SELECT NOW(); ALTER TABLE foo ALTER COLUMN id SET DEFAULT 0, ALGORITHM=INSTANT; SELECT NOW(); +---------------------+ | NOW() | +---------------------+ | 2026-03-05 01:59:32 | +---------------------+ 1 row in set (0.01 sec) ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction +---------------------+ | NOW() | +---------------------+ | 2026-03-05 01:59:37 | +---------------------+ 1 row in set (0.00 sec) -- session 3 mysql> SELECT NOW(); SELECT * FROM foo; SELECT NOW(); +---------------------+ | NOW() | +---------------------+ | 2026-03-05 01:59:34 | +---------------------+ 1 row in set (0.01 sec) Empty set (3.03 sec) +---------------------+ | NOW() | +---------------------+ | 2026-03-05 01:59:37 | +---------------------+ 1 row in set (0.00 sec) 1秒未満で完了するか 続いおの条件は「1秒未満で完了するかどうか」です. これに぀いおは具䜓的なケヌスを玹介するこずは難しいのですが, 䟋えば CREATE TABLE 文, 空もしくは十分少ないレコヌド数に察するメタデヌタの倉曎で完結しない DDL[^5] などがこれに圓たりたす. ここでなぜ「1秒未満」ずいう条件を付䞎しおいるかに぀いおですが, MySQL の DDL はたずえ online ずしおも replication を構成しおいるずきには䞋蚘の制限がありたす[^6]: Long running online DDL operations can cause replication lag. An online DDL operation must finish running on the source before it is run on the replica. Also, DML that was processed concurrently on the source is only processed on the replica after the DDL operation on the replica is completed. online DDL ずしおも replica で実行される前に source で完了しおいる必芁があり, たた source で䞊行で実行されおいる DML は replica での DDL が完了した埌に実行されたす. ぀たり, source で䞊行実行されおいる DML は replica では DDL が完了するたでブロックされるずいうこずです. これは source 偎で(online) DDL による source 偎の table definition の倉曎ず䞊行実行されおいる DML の察応が replica 偎でも同様にしお再珟される必芁がありたす. そのため replica 偎でも table defintion の倉曎ず DML の敎合性を担保するためにこのような仕組みずなっおいたす. 冒頭の蚘事のようにメルカリのデヌタサむズは非垞に巚倧で䞭には DDL 完了に1日以䞊かかるものもあり, そのようなテヌブルぞの DDL による replication 遅延を防ぐために, 基本的に即座に終わらない DDL はそのたた実行しないようにしおいたす. 実際に DDL が 1s 未満で完了するかどうかは経隓則に基づくこずが倚いですが, 䟋えばサヌビスで皌働しおいないホストで SET sql_log_bin=0 を実行しおバむナリログに出力しないようにしお実枬するなどで蚈枬可胜です. たた, DDL 自䜓が 1s 未満で完了するずしおも先の metadata lock による圱響は考慮する必芁があるため, この堎合も同様に lock_wait_timeout を調敎する必芁がありたす. gh-ost で察応可胜か 時間のかかる DDL を実行する堎合, メルカリでは gh-ost を採甚しおいたす . gh-ost を利甚できるかどうかに぀いおはリ゜ヌス的な制限(テヌブルコピヌを䌎うため䜙剰なディスクサむズが必芁, 通垞の曎新ず gh-ost による backfill/差分同期による replication 遅延圱響)や機胜的な制限(UNIQUE KEY の䞀郚に ENUM が含たれる堎合の性胜劣化[^7])がない限り gh-ost を利甚しおおり, DDL 実行オペレヌションで最も数の倚いケヌスです. もしそれらを満たさない堎合には Rolling Upgrade, ぀たり党 replica に察しお DDL を実行し最埌に source を切り替えるずいったこずを行いたす. なぜ ENUM を含む堎合に性胜劣化するのか MySQL の 公匏ドキュメント によるず ENUM は文字列順ではなく内郚 index 順で゜ヌトされたすが, これは Go 蚀語[^8]の文字列によるハンドリングず異なりたす. この ENUM の取り扱いの䞍䞀臎による iteration 時のデヌタ欠損を避けるために, gh-ost では UNIQUE KEY に ENUM が含たれる堎合には CONCAT(...) により明瀺的な文字列ずしお取り扱われたす[^9]. この時, ORDER BY CONCAT(...) ASC が実行されるこずになり結果ずしお iteration のたびに Creating Sort Index が発生し性胜, 負荷ずもに劣化する可胜性がありたす. DM を甚いた DDL 実行 ここから TiDB の話に移りたす. 前述の通りメルカリでは移行に䌎う停止時間をなるべく短くするために DM を甚いお MySQL ず TiDB で差分同期をし぀぀切り替えを進めおいたす: この時, 前述の条件 3 の堎合にどのような挙動になるかを考えおみたす. こちらのドキュメント の通り, DM には online-ddl ずいうフラグがあり pt-osc や gh-ost ずいった online migration tool のナヌスケヌスをカバヌしおいたす. ここからは gh-ost を䟋にしお説明しおいきたす. たず, gh-ost で test database の foo table に DDL が適応される流れに぀いお説明したす: メタデヌタテヌブル(ghc) を䜜成 Create /* gh-ost */ table test._foo_ghc realtable をもずに切り替え埌のテヌブル(gho)を䜜成 Create /* gh-ost */ table test._foo_gho like test.foo gho に DDL の適応 ALTER /* gh-ost */ table test._foo_gho ... realtable から gho ぞの backfill backfill 完了埌 realtable から gho ぞの差分同期 差分同期完了埌 RENAME 文を䜿っお cutover RENABLE TABLE foo TO _foo_del, _foo_gho TO foo このフロヌで online-ddl が有効化されおいる堎合に DM はどのような挙動になるでしょうか. メタデヌタテヌブル(ghc) を䜜成 DM は ghc テヌブルを䜜成しない realtable をもずに切り替え埌のテヌブル(gho)を䜜成 DM は gho テヌブルを䜜成しない, その代わりにメタデヌタテヌブル dm_meta.{task_name}_onlineddl を初期化する DELETE FROM dm_meta.{task_name}_onlineddl WHERE id = {server_id} and ghost_schema = {ghost_schema} and ghost_table = {ghost_table}; gho に DDL の適応 DM が実行される DDL をメタデヌタテヌブル dm_meta.{task_name}_onlineddl に保存する この DDL は埌に利甚される realtable から gho ぞの backfill DM は realtable ぞの曎新のみ TiDB に同期する gho ぞの曎新はすべお砎棄される backfill 完了埌 realtable から gho ぞの差分同期 4 ず同様に realtable ぞの曎新のみ同期 差分同期完了埌 RENAME 文を䜿っお cutover DM は cutover の RENAME 文を分割し, gho table から realtable ぞの RENAME 実行の際に䞋蚘を実斜する 3 で保存した DDL を取埗 DDL の gho を realtable に眮換 眮換された DDL を実行 ALTER table test.foo ...; このようにしお DM は OnlineDDL ツヌルを利甚する際に realtable から gho ぞの同期に䌎う凊理を削枛しおいたす( online-ddl=false を指定した堎合は通垞通り gho/ghc などが䜜成される). たずめるず䞋蚘のようになりたす: MySQL TiDB メタデヌタテヌブル(ghc) を䜜成 ghc テヌブルは䜜成しない realtable をもずに切り替え埌のテヌブル(gho)を䜜成 gho テヌブルは䜜成せず DM のメタデヌタテヌブルを初期化 gho に DDL の適応 実行予定の DDL をメタデヌタテヌブルに保存 realtable から gho ぞの backfill realtable ぞの曎新のみ TiDB に同期 backfill 完了埌 realtable から gho ぞの差分同期 realtable ぞの曎新のみ TiDB に同期 差分同期完了埌 RENAME 文を䜿っお cutover RENAME 文を分割し保存しおいた DDL を実際に realtable に察しお実行 gh-ost 利甚時の DM の挙動の比范 DDL 実行時のトラブル メルカリでは online-ddl=true & gh-ost による DDL 実行で運甚しおおり, 特に倧きな問題もなく運甚できおいたした. しかしある時の DDL 実行で問題が発生したす. その問題ずは DM の replication lag が通垞 1~2s 未満だったものが突劂 1h 以䞊遅延するずいう事象でした. DM の status は RUNNING にも関わらずこの様に Replication QPS(DM syncer の完了した Job 数)が 16:00 頃から 0 になっおおり, DML が䜕も実行されなくなっおいたした: TiDB のサポヌトチヌムずずもに調査したずころ, この QPS が停止したタむミングで䞋蚘の DDL が実行されおいたこずがわかりたした. ALTER TABLE `mercari`.`foo` MODIFY COLUMN `bar_id` int(10) UNSIGNED NOT NULL; この DDL は先の MySQL における DDL 実行パタヌンにおいお gh-ost を利甚するものであったため, 先で玹介した cutover( RENAME TABLE ) 実行時に ALTER が実行されおおりこの DDL により DM の遅延が発生しおいるこずがわかりたした. 原因はわかりたしたが, なぜ DM が遅延したのでしょうか. これは先に玹介した Online DDL の replica で実行される制限ず同じ理由で, TiDB が盎接 MySQL の binlog を読めないため DM が先の source/replica での table defnition ず DML の敎合性担保を保蚌するための仕組みずなっおいたす. では v8.5.3 を䟋に実際にコヌドの䞭をみおみたしょう[^10]: // dm/syncer/syncer.go#L713 func (s *Syncer) Process(ctx context.Context, pr chan pb.ProcessResult) { // ... err := s.Run(newCtx) if err != nil { // returned error rather than sent to runFatalChan // cancel goroutines created in s.Run cancel() } // ... } // dm/syncer/syncer.go#L1741 func (s *Syncer) Run(ctx context.Context) (err error) { // ... s.runWg.Add(1) go s.syncDML() s.runWg.Add(1) go func() { defer s.runWg.Done() // also need to use a different ctx. checkpointFlushWorker worker will be closed in the first defer s.checkpointFlushWorker.Run(s.tctx) }() s.runWg.Add(1) go s.syncDDL(adminQueueName, s.ddlDBConn, s.ddlJobCh) // ... } // dm/syncer/syncer.go#L1419 func (s *Syncer) syncDDL(queueBucket string, db *dbconn.DBConn, ddlJobChan chan *job) { defer s.runWg.Done() var err error for { ddlJob, ok := <-ddlJobChan if !ok { return } // ... if !ignore { // ... affected, err = db.ExecuteSQLWithIgnore(s.syncCtx, s.metricsProxies, errorutil.IsIgnorableMySQLDDLError, ddlJob.ddls) // ... } } } // dm/syncer/ddl.go#L221 func (ddl *DDLWorker) HandleQueryEvent(ev *replication.QueryEvent, ec eventContext, originSQL string) (err error) { // ... if err = ddl.flushJobs(); err != nil { return err } return ddl.strategy.handleDDL(qec) } // dm/syncer/syncer.go#L3210 func (s *Syncer) flushJobs() error { flushJobSeq := s.getFlushSeq() s.tctx.L().Info("flush all jobs", zap.Stringer("global checkpoint", s.checkpoint), zap.Int64("flush job seq", flushJobSeq)) job := newFlushJob(s.cfg.WorkerCount, flushJobSeq) _, err := s.handleJobFunc(job) return err } // dm/syncer/syncer.go#L1115 func (s *Syncer) handleJob(job *job) (added2Queue bool, err error) { // ... s.addJob(job) // ... } // dm/syncer/syncer.go#L1016 func (s *Syncer) addJob(job *job) { // ... tp := job.tp switch tp { case flush: s.jobWg.Add(1) s.dmlJobCh <- job case ddl: s.updateJobMetrics(false, adminQueueName, job) s.jobWg.Add(1) startTime := time.Now() s.ddlJobCh <- job s.metricsProxies.AddJobDurationHistogram.WithLabelValues("ddl", s.cfg.Name, adminQueueName, s.cfg.SourceID).Observe(time.Since(startTime).Seconds()) // ... } } // dm/syncer/syncer.go#L1617 func (s *Syncer) syncDML() { defer s.runWg.Done() dmlJobCh := s.dmlJobCh if s.cfg.Compact { dmlJobCh = compactorWrap(dmlJobCh, s) } causalityCh := causalityWrap(dmlJobCh, s) flushCh := dmlWorkerWrap(causalityCh, s) for range flushCh { s.jobWg.Done() } } // dm/syncer/syncer.go#L1419 func (s *Syncer) syncDDL(queueBucket string, db *dbconn.DBConn, ddlJobChan chan *job) { defer s.runWg.Done() var err error for { ddlJob, ok := <-ddlJobChan if !ok { return } // ... if !ignore { // ... affected, err = db.ExecuteSQLWithIgnore(s.syncCtx, s.metricsProxies, errorutil.IsIgnorableMySQLDDLError, ddlJob.ddls) // ... } } } この郚分で binlog から DDL むベントが来たずきに, たず DML の flush を行いたす. これは DML queue に入っおいる DML を䞀床すべお䞋流(TiDB)にお実行するため, s.jobWg.Wait() それらの完了を埅機したす. その埌 DDL job を DDL queue に投入し, 再び s.jobWg.Wait() で䞋流(TiDB)で DDL 実行が完了するたで埅機したす. この DDL による wait で埅機しおいる間 binlog むベント凊理ルヌプはブロックされるため, DDL が完了するたで DM は埌続のむベントを凊理しないずいうこずになりたす. online-ddl=true 蚭定時に gh-ost を利甚した DDL の実行は䞋蚘のようになりたす: この様に gh-ost の cut-over(RENAME) 実行時に downstream 偎で実際の DDL が発行されそれが完了するたで DML はブロックされるため, DDL が完了するたで replication が遅延するこずになりたす. DM を利甚し぀぀安党に DDL を実行するには この様に online-ddl は gh-ost など online schema change tool の利甚時に同期に必芁な無駄を削枛させるためのものなため, 指定したずしおも䞋流(TiDB)での DDL の実行完了を埅぀必芁がありたす. これは冒頭の無停止で段階的に移行しおいく際にいく぀か問題がある堎合がありたす. MySQL から TiDB ぞ移行する際にはサヌビスぞの圱響が少ないもの(分析基盀のための CDC など)から読み蟌みを移行させおいきたすが, これらの䞭には倧きな遅延が蚱容できないものもあるため, 数時間実行にかかる DDL は圱響を䞎える可胜性がありたす. 䞀方でメルカリのデヌタベヌスはいずれも巚倧であり TiDB Dumpling や TiDB Lightning による export/import でも数日以䞊かかり, DDL 実行のために DM を停止, ぀たり TiDB Cluster を再䜜成するずいうオペレヌションも珟実的ではありたせん. そのため, メルカリでは䞋蚘のように DDL の実行方法をケヌス分けしおいたす: 先の玹介のように online-ddl を有効化するず MySQL 䞊で cutover( RENAME TABLE ) されたタむミングで TiDB 偎で DDL が実行されたす. 仮にこの DDL が䟋えば MODIFY COLUMN のように䜕床でも実行可胜な堎合は, 先に TiDB 偎のみ DDL を実行しおおいお gh-ost をするこずで2回目の(実質意味がない) DDL では即座に終了するため, 実際の DDL が長時間でも DM の遅延を最小に抑えるこずが可胜です. 前のブログ にあるようなレコヌド数が倚くさらに INDEX で倚数利甚されおいるような column に察する MODIFY COLUMN などには有甚ず蚀えたす. それ以倖の堎合(䟋えば INDEX 远加など)は実行時間やビゞネス芁件によっおかわりたすが, 遅延を蚱容しお gh-ost を実行する, Binlog Event Filter により該圓の DDL だけ陀倖するなど察応が考えられたす. たずめ 今回は DM で MySQL ず TiDB を同期しおいるずきに DDL をなるべく安党に実行する方法を玹介したした. DM を利甚する際に参考にしおいただけるず幞いです. 珟圚メルカリでは DBRE の EM を募集しおいたす, 詳しくは こちら をご芧ください. [^1]: ref: https://pingcap.co.jp/case-study/mercari-tidb-cloud/   [^2]: ref: https://dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl-operations.html   [^3]: 末尟远加か぀芁玠の個数が byte を跚がない堎合のみ該圓 [^4]: ref: https://dev.mysql.com/doc/refman/8.4/en/metadata-locking.html   [^5]: 䟋えば INDEX や column の操䜜(远加/削陀/タむプ倉曎) [^6]: ref: https://dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl-limitations.html   [^7]: ref: https://github.com/github/gh-ost/blob/master/doc/requirements-and-limitations.md   [^8]: ref: gh-ost は Go 蚀語, pt-osc は Perl で実装されおいる [^9]: ref: https://github.com/github/gh-ost/issues/273   [^10]: ref: https://github.com/pingcap/tiflow/blob/v8.5.3/  
LifeKeeperの『困った』を『できた』に倉えるサポヌト事䟋から孊ぶトラブルシュヌティング再発防止策 こんにちは、SCSKの前田です。 い぀も TechHarmony をご芧いただきありがずうございたす。 システムのリプレヌスやハヌドりェア曎新のタむミングで蚪れる、「ミドルりェアのバヌゞョンアップ」。 「サポヌト切れEOS察応」や「魅力的な新機胜の远加」など、OSのパッチ適甚ずはたた違った、期埅ず緊匵が入り混じる䞀倧むベントではないでしょうか。 しかし、HAクラスタヌ゜フトりェアであるLifeKeeperにおいお、この「バヌゞョンアップ」は単なるファむルの眮き換えではありたせん。 「むンストヌラヌを実行しお、バヌゞョン番号が䞊がれば完了」   そう思い蟌んで䜜業を進めた結果、再起動埌に蚭定ファむルが初期倀に戻っおいたり、長幎動いおいたスクリプトが突然゚ラヌを吐き始めたりずいった、予期せぬトラブルに盎面するこずがありたす。 本連茉䌁画「LifeKeeper の『困った』を『できた』に倉えるサポヌト事䟋から孊ぶトラブルシュヌティング再発防止策」では、サポヌトセンタヌに蓄積された「生のトラブル事䟋」を元に、安定運甚のための実践的な知恵を共有しおいきたす。 はじめに成功ぞのロヌドマップを描く 連茉第2回ずなる今回は、LifeKeeper本䜓やDataKeeperのバヌゞョンアップに焊点を圓おたす。 バヌゞョンアップ䜜業においお、最も怖いのは 「芋えない倉化」 です。 むンストヌラヌは䟿利ですが、それが裏偎でどの蚭定を匕き継ぎ、どの蚭定をリセットするのか、たた新しいバヌゞョンが叀い蚭定をどう解釈するのかは、リリヌスノヌトの现郚を読み蟌たない限り芋えおきたせん。 今回は、実際にサポヌトぞ寄せられた「バヌゞョンアップ倱敗事䟋」を以䞋の3぀の「萜ずし穎Trap」に分類したした。 蚭定ず環境の「サむレント倉化」 過去の「たあいいか」が牙をむく 近道は「急がば回れ」 これらの事䟋から「なぜ倱敗したのか」を孊び、確実に成功させるためのチェックポむントロヌドマップを解説したす。 その他の連茉䌁画は以䞋のリンクからどうぞ 【リ゜ヌス起動・フェむルオヌバヌ倱敗の深局 #1】EC2リ゜ヌスが起動しないクラりド連携の盲点ずデバッグ術 – TechHarmony 【リ゜ヌス起動・フェむルオヌバヌ倱敗の深局 #2】ファむルシステムの思わぬ萜ずし穎゚ラヌコヌドから原因を読み解く – TechHarmony 【リ゜ヌス起動・フェむルオヌバヌ倱敗の深局 #3】蚭定ミス・通信障害・バヌゞョン違いの深局ず再発防止策 – TechHarmony 【OS・LKバヌゞョンアップで泣かないために #1】OSバヌゞョンは倉えおいないのにカヌネル曎新の「萜ずし穎」ず互換性の真実 – TechHarmony 【実録】LifeKeeperバヌゞョンアップの「困った」事䟋ファむル ここからは、実際のサポヌト問い合わせをベヌスにしたケヌススタディです。 「自分の環境でも起こりうるかもしれない」 ずいう芖点でご芧ください。 Trap 1蚭定ず環境の「サむレント倉化」 バヌゞョンアップによっお、今たで䜿っおいた蚭定や環境が 「静かに」 倉わっおしたう ケヌスです。 ■ケヌスAアップデヌトしたら蚭定が消えたLinux版 「v9.5.2からv9.9.1ぞアップデヌトしたした。゚ラヌなく完了したのですが、再起動埌になぜかプロキシ蚭定などが効かなくなっおいたす 」 発生状況:  ã‚¢ãƒƒãƒ—デヌト䜜業自䜓は成功したものの、LifeKeeperの動䜜蚭定ファむル /etc/default/LifeKeeper に蚘述しおいたカスタム蚭定が消倱しおいたした。 原因: LifeKeeperの仕様により、曎新むンストヌル時に 䞀郚の蚭定ファむルがデフォルト倀に戻る䞊曞きされる 挙動ずなっおいたした。 教蚓:  ã€Œèš­å®šã¯ã™ã¹ãŠè‡ªå‹•的に匕き継がれるはず」ずいう思い蟌みは危険です。特にメゞャヌバヌゞョンをたたぐ曎新では、バックアップず埩元手順が必須です。 ■ケヌスBスクリプトが動かないPerlの眠Windows版 「v8.9からv8.10.2ぞ䞊げようずしおいたす。パラメヌタ倉曎は䞍芁ず聞きたしたが、本圓にそのたた䞊げお倧䞈倫でしょうか」 リスク:  èª¿æŸ»ã®çµæžœã€LifeKeeperに同梱されおいるPerlのバヌゞョンが、v8.10.1以降で「5.8系」から「5.32系」ぞず䞀気にアップグレヌドされおいるこずが刀明したした。 教蚓:  Genericリ゜ヌスなどでPerlスクリプトを䜿甚しおいる堎合、蚀語仕様の倉曎によりスクリプトが動䜜しなくなる可胜性がありたす。アプリケヌションだけでなく、ミドルりェアが䟝存する 「蚀語環境」の倉化 も重芁なチェックポむントです。 Trap 2過去の「たあいいか」が牙をむく 叀いバヌゞョンでは蚱容されおいたあるいは無芖されおいた蚭定の䞍備が、新しいバヌゞョンの「厳栌なチェック」によっお゚ラヌずしお顕圚化するケヌスです。 ■ケヌスC亡霊IPがアラヌトを匕き起こす 「OSずLifeKeeperを曎新した埌、ログに failed quickCheck due to ALRM signal ずいう゚ラヌが倚発するようになりたした。以前は出おいなかったのですが 」 原因:  IPリ゜ヌスの監芖リスト pinglist に、既に撀去枈みで疎通できない叀いIPアドレスが残っおいたした。 なぜ今:  ãƒãƒŒã‚žãƒ§ãƒ³ã‚¢ãƒƒãƒ—に䌎い チェック凊理やリトラむの挙動が倉化厳栌化 し、叀いIPぞの応答埅ちが積み重なった結果、タむムアりトALRM signalが発生しおいたした。 教蚓:  ã€Œä»Šã¯äœ¿ã£ãŠã„ないけど残っおいる蚭定」は、バヌゞョンアップ時の最倧の敵です。曎新䜜業はゎミ掃陀の絶奜の機䌚ず捉えたしょう。 ■ケヌスDディスクに名前がないUUID問題 「バヌゞョンアップ埌、DataKeeperリ゜ヌスで『䞀意の識別子がない』ずいう譊告が出たり、パヌティション情報が正しく取埗できなくなりたした」 原因:  LifeKeeper/DataKeeperの新しいバヌゞョンでは、ディスクを䞀意に特定するために 「UUID」の䜿甚が必須化たたは厳栌化 されたした。叀い環境で「MBR圢匏」のパヌティションを䜿っおいたため、UUIDを持たず、新しいバヌゞョンの芁件を満たせなくなっおいたした。 教蚓:  ã‚œãƒ•トりェアの進化に合わせお、むンフラ偎パヌティションテヌブル等もGPT圢匏ぞのモダン化が必芁になるこずがありたす。 Trap 3近道は「急がば回れ」 手順を省略したり、無理なアップデヌトパスを通ろうずしお倱敗するケヌスです。 ■ケヌスE飛ばしすぎたバヌゞョンアップ 「v9.6.xからv9.8.1ぞ䞀気にアップデヌトしようずしたら倱敗したした。2䞖代前からの曎新はサポヌトされおいるはずですが 」 原因:  åŸºæœ¬çš„には盎接アップデヌトが可胜ですが、 この特定のバヌゞョンv9.8.1においおは 内郚パッケヌゞの倧幅な構成倉曎 があったため、䟋倖的にv9.7やv9.8.0を経由する「ステップアップグレヌド」が必芁でした。 教蚓:  ã€Œã„぀ものルヌルN-2たでOKなどが今回も適甚される」ずは限りたせん。リリヌスノヌトには必ず 「アップグレヌドの泚意点」や「䟋倖的なパス」 が蚘茉されおいたすので、慣れおいる䜜業でも必ず目を通したしょう。 ■ケヌスFGUIの衚瀺がおかしい 「DataKeeper曎新埌、GUI䞊でゞョブ情報が衚瀺されなくなりたした」 解決策: 調査の結果、内郚情報の䞍敎合が起きおいたした。このケヌスでは、無理に修正するよりも「再むンストヌルしおゞョブを再䜜成」した方が、結果ずしお早く、確実に解消したした。 教蚓:   バヌゞョンが倧きく離れおいる堎合や挙動がおかしい堎合 は、䞊曞きアップデヌトに固執せず、蚭定バックアップをずった䞊での「䜜り盎し再䜜成」が最短ルヌトになるこずがありたす。 「再発させない」成功ぞのチェックリスト 䞊蚘の倱敗事䟋から導き出した、バヌゞョンアップ䜜業前に確認すべき「転ばぬ先の杖」チェックリストです。蚈画段階でぜひご掻甚ください。 ■LifeKeeper/DataKeeper バヌゞョンアップ事前確認シヌト [  ] 【パスの確認】 珟圚のバヌゞョンからタヌゲットバヌゞョンぞ「盎接」アップデヌト可胜ですか䞭継バヌゞョンが必芁ありたせんか [  ] 【蚭定ファむルのバックアップ】 曎新時に初期化されるファむル /etc/default/LifeKeeper 等を特定しおいたすか それらの手動バックアップを取埗し、曎新埌に埩元する手順を組み蟌みたしたか [  ] 【蚀語・環境の差異】 PerlやPythonなど、LifeKeeperが利甚するランタむムのバヌゞョンに倉曎はありたせんか自䜜スクリプトぞの圱響確認 ディスクのパヌティション圢匏は新しいバヌゞョンの芁件UUID必須/GPT掚奚などを満たしおいたすか [  ] 【䞍芁蚭定の削陀ゎミ掃陀】 IPリ゜ヌスの pinglist に、珟圚疎通できない「亡霊IP」が残っおいたせんか [  ] 【OSずの敎合性】 OS自䜓のカヌネルアップデヌトを行う堎合、LifeKeeperの再むンストヌルやモゞュヌル再コンパむルの手順を確認したしたか [  ] 【リカバリプラン】 曎新むンストヌルが䞍敎合を起こした堎合に備え、䞀床アンむンストヌルしお「新芏むンストヌル蚭定埩元たたは再䜜成」に切り替える刀断基準を持っおいたすか ベストプラクティス成功ぞの近道 トラブルを防ぐために、明日からできる「ベストプラクティス」を3぀提案したす。 「リリヌスノヌト」は宝の地図 リリヌスノヌトを「バグ修正のリスト」だず思っおいたせんか 本圓に芋るべきは「制限事項 (Known Issues)」 ず 「倉曎点 (Migration/Changes)」です。ここには「蚭定ファむルが初期化される」「UUIDが必須になる」ずいった重芁情報が必ず曞かれおいたす。 ステヌゞング環境でのリハヌサルは必須 机䞊の確認だけでは、「pinglistのタむムアりト」や「Perlの互換性」ずいった環境䟝存のトラブルは芋抜けたせん。本番環境のクロヌンたたは同等構成を甚意し、実際にバヌゞョンアップ手順を流すリハヌサルを行っおください。 倧幅な曎新は「再䜜成」も芖野に 数幎前のバヌゞョンから䞀気に最新版にするような堎合、継ぎ接ぎのアップデヌトを繰り返すより、「蚭定情報を控えお、クリヌンむンストヌル埌に再蚭定する」方が、朜圚的なゎミが残らず、結果的に安定皌働に぀ながるこずが倚々ありたす。「䞊曞き」にこだわらない柔軟性も重芁です。 たずめ バヌゞョンアップ時のトラブルは、倚くの堎合「準備䞍足」や「思い蟌み」の隙間に入り蟌むものです。 しかし、今回ご玹介した事䟋のように、事前に 「䜕が倉わるのか」「䜕が消えるのか」「今の蚭定にゎミはないか」 を確認しおおけば、そのほずんどは防げたす。 「LifeKeeperの『困った』を『できた』に倉える」 今回のロヌドマップを参考に、ぜひ安心・安党なバヌゞョンアップ蚈画を立おおください。 次回予告 次回からは新章に突入 テヌマは「クラりド環境特有の萜ずし穎AWS/Azure連携でハマるポむント」です。 クラりドならではの「オンプレミスず同じ感芚で蚭定したら動かない」ずいうトラブル。 その第䞀匟ずしお、 AWS環境でのLifeKeeper安定皌働術 にフォヌカスしたす。 「Route53のDNSが切り替わらない」「䟿利なはずの『Auto Recovery』がLifeKeeperず喧嘩する」ずいったAWS特有の事䟋ず、EC2・S3連携の泚意点を培底解説したす。お楜しみに 詳しい内容をお知りになりたいかたは、以䞋のバナヌからSCSK LifeKeeper公匏サむトたで

動画

該圓するコンテンツが芋぀かりたせんでした

曞籍