地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【MySQL】InnoDBはどのようにデータの破損を検出しているのか

この記事は「MySQL Advent Calendar 2023」の14日目の記事です!

一言で書くと

InnoDBはdiskに書くときページ単位でCRC計算してるそれを使って検出してる

本文

MySQLに限った話ではないですがデータ自体が破損するケースは往々にしてあります。よくある(?)例としては以下のような原因があります。

  • ハードウェア起因
  • ソフトウェア起因
  • 突然のシャットダウン(カーネルパニック、電源断、コンセントブチ抜き...)
  • ファイルシステムエラー
  • ヒューマンエラー(コマンドミスとか悪意ある人物が侵入してきたとか)

こういったことが起きても問題とならないようにInnoDBではchecksumを用いた書き込みを行っています。InnoDBでは、データの整合性を保つために、ディスクには16KBのブロック単位でデータを書き込む必要があります。これはトランザクションのAtomicの担保を意味し書き込み操作が完全に行われるか、全く行われないかのどちらかであることを意味します。InnoDBは各ブロックにチェックサムを計算し、保存します。これにより、データの整合性を保証し、ページの破損を検出することができます。

ページ破損を検出したら

MySQLのエラーログに以下のようなメッセージが出力されます。MySQL、(特にInnoDBストレージエンジン)がページ破損を検出したことを示しています。(InnoDBはページ番号4651のページで破損を検出したことも書かれていて、これは、チェックサムの不一致によって確認されています。)

InnoDB: Page may be an index page where index id is 22
InnoDB: (index "PRIMARY" of table "test"."t")
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 4651.
InnoDB: You may have to recover from a backup.
InnoDB: It is also possible that your operating
InnoDB: system has corrupted its own file cache
InnoDB: and rebooting your computer removes the
InnoDB: error.
InnoDB: If the corrupt page is an index page
InnoDB: you can also try to fix the corruption
InnoDB: by dumping, dropping, and reimporting
InnoDB: the corrupt table. You can use CHECK
InnoDB: TABLE to scan your table for corruption.
InnoDB: See also http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 4651.
InnoDB: You may have to recover from a backup.

こうなってしまったらあとはログや以下の記事にも書かれているようにリカバリ処理を実行する必要があります。(ちなみにクラッシュ後に自動的に再起動されるように設定する方法は、使用しているオペレーティングシステムとその管理システムに依存します。systemdとかでも自動起動とかは可能です)

www.percona.com

innodb_force_recoveryをつけて再起動することで壊れ方次第ですが復旧することができます(クラッシュリカバリは過去に色々書いてるのでみていただければと)

dev.mysql.com

innodbチェックサムアルゴリズムは指定できる

ディスクブロックに格納されている checksum を生成および検証する方法はinnodb_checksum_algorithmで指定することができるようです。デフォルト値はcrc32innodbを指定するとInnoDB固有のチェックサムアルゴリズムを使用するらしいです。これは、古いバージョンのMySQLで標準的に使用されていたアルゴリズムとのこと。noneを指定することもできるらしいです。整合性を無視してパフォーマンスが欲しい場面とかでは有効なのでしょうか。(チェックサムハードウェアアクセラレーターを導入することでハードウェアの資源を借りつつみたいな世界がどこかにあるのかなと思いましたが知ってる方いたら教えてください)

dev.mysql.com

innochecksum オフラインでチェックサムの整合性確認ができる

dev.mysql.com

innochecksumはMySQL で使用される InnoDB ストレージエンジンのテーブルスペースファイル(.ibd ファイル)のチェックサムを検証および再計算するためのコマンドラインツールです。InnoDBはページの破損を検出した時点で停止するのでその状態でこのツールは、InnoDB テーブルスペースのページの整合性をチェックするのに役立ちます。当たり前ですがオンラインでやろうとすると整合性が取れてるページでも不整合ありと出力したりします。(5.7以降だとどうやらオンラインだとそもそもエラーになるらしいです。)

# 実行イメージ
$ innochecksum -d ibdata1

www.percona.com

終わりに

データ破損。怖いですね(?)