流血の MySQL クラッシュ修復事例を思い出してください

要約: 本日は、MySQL データベース クラッシュの修理事例をお届けします。

この記事は、HUAWEI CLOUD コミュニティ「Remember a MySQL crash repair case, no need to delete the database and run away」、著者: Glacier から共有されています。

問題の説明

MySQL ソース コードの調査、MySQL ソース コードのデバッグおよびストレス テスト中に、MySQL がクラッシュしました。問題は、実際にクラッシュすることです。また、InnoDB ファイルも破損しています。! 幸いなことに、デバッグ環境で発生しました.この問題を解決する方法を簡単に見てみましょう.データアクセス、検証、比較、MySQL ソースコードのデバッグと追跡、破損した InnoDB ファイルの修復、要約などの一連のプロセスを経て、この記事は将来、オンライン本番環境が本当に実現すれば、逃げる心配はありません.MySQLクラッシュ問題を数分で解決できます! ! 次のようにエラー ログを確認します。

-----------------------------------------
161108 23:36:45 mysqld_safe Starting mysqld daemon with databases from /usr/local/mysql/var
2022-08-25 23:36:46 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2022-08-25 23:36:46 5497 [Note] Plugin 'FEDERATED' is disabled.
2022-08-25 23:36:46 7f11c48e1720 InnoDB: Warning: Using innodb_additional_mem_pool_size is DEPRECATED. This option may be removed in future releases, together with the option innodb_use_sys_malloc and with the InnoDB's internal memory allocator.
2022-08-25 23:36:46 5497 [Note] InnoDB: Using atomics to ref count buffer pool pages
2022-08-25 23:36:46 5497 [Note] InnoDB: The InnoDB memory heap is disabled
2022-08-25 23:36:46 5497 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2022-08-25 23:36:46 5497 [Note] InnoDB: Memory barrier is not used
2022-08-25 23:36:46 5497 [Note] InnoDB: Compressed tables use zlib 1.2.3
2022-08-25 23:36:46 5497 [Note] InnoDB: Using CPU crc32 instructions
2022-08-25 23:36:46 5497 [Note] InnoDB: Initializing buffer pool, size = 16.0M
2022-08-25 23:36:46 5497 [Note] InnoDB: Completed initialization of buffer pool
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 5.
InnoDB: You may have to recover from a backup.
2022-08-25 23:36:46 7f11c48e1720 InnoDB: Page dump in ascii and hex (16384 bytes):
 len 16384; hex 7478d078000000050000000000000000000000000f271f4d000700000000000000000000000000000000001b4000000000000000000200f20000000000000006000000000000002d000000000000002e000000000000002f0000000000000030000000000(省略很多类似代码)
InnoDB: End of page dump
2022-08-25 23:36:46 7f11c48e1720 InnoDB: uncompressed page, stored checksum in field1 1954074744, calculated checksums for field1: crc32 993334256, innodb 2046145943, none 3735928559, stored checksum in field2 1139795846, calculated checksums for field2: crc32 993334256, innodb 1606613742, none 3735928559, page LSN 0 254222157, low 4 bytes of LSN at page end 254221236, page number (if stored to page already) 5, space id (if created with >= MySQL-4.1.1 and stored already) 0
InnoDB: Page may be a transaction system page
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 5.
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: Ending processing because of a corrupt database page.
2022-08-25 23:36:46 7f11c48e1720  InnoDB: Assertion failure in thread 139714288817952 in file buf0buf.cc line 4201
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
03:36:46 UTC - mysqld got signal 6 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.
key_buffer_size=16777216
read_buffer_size=262144
max_used_connections=0
max_threads=1000
thread_count=0
connection_count=0
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 798063 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.
Thread pointer: 0x0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 0 thread_stack 0x40000
/usr/local/mysql/bin/mysqld(my_print_stacktrace+0x35)[0x8e64b5]
/usr/local/mysql/bin/mysqld(handle_fatal_signal+0x41b)[0x652fbb]
/lib64/libpthread.so.0(+0xf7e0)[0x7f11c44c77e0]
/lib64/libc.so.6(gsignal+0x35)[0x7f11c315d625]
/lib64/libc.so.6(abort+0x175)[0x7f11c315ee05]
/usr/local/mysql/bin/mysqld[0xa585c5]
/usr/local/mysql/bin/mysqld[0xa6c7b4]
/usr/local/mysql/bin/mysqld[0xa6cbc7]
/usr/local/mysql/bin/mysqld[0xa5bce2]
/usr/local/mysql/bin/mysqld[0xa1e2ba]
/usr/local/mysql/bin/mysqld[0xa0bf60]
/usr/local/mysql/bin/mysqld[0x95a427]
/usr/local/mysql/bin/mysqld(_Z24ha_initialize_handlertonP13st_plugin_int+0x48)[0x58f788]
/usr/local/mysql/bin/mysqld[0x6e4a36]
/usr/local/mysql/bin/mysqld(_Z11plugin_initPiPPci+0xb3e)[0x6e826e]
/usr/local/mysql/bin/mysqld[0x582d85]
/usr/local/mysql/bin/mysqld(_Z11mysqld_mainiPPc+0x4d8)[0x587d18]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x7f11c3149d5d]
/usr/local/mysql/bin/mysqld[0x57a019]
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
161108 23:36:46 mysqld_safe mysqld from pid file /usr/local/mysql/var/VM_241_49_centos.pid ended
------------------------------------------------------------------------------

問題分析

ログから、innodb エンジンに問題があることがわかります。ログは http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html を要求して、強制リカバリの方法を表示します。mysql 構成ファイル my.cnf で [mysqld] フィールドを見つけて、innodb_force_recovery=1 を追加します。

[mysqld]
innodb_force_recovery = 1

innodb_force_recovery = 1 が有効にならない場合は、2 から 6 までの数を試すことができます

その後、mysql を再起動すると、再起動は成功します。次に、mysqldump または pma を使用してデータをエクスポートし、修復操作を実行します。修復が完了したら、パラメーターをコメント アウトし、既定値の 0 に戻します。

構成ファイルのパラメーター: innodb_force_recovery

innodb_force_recovery は、InnoDB ストレージ エンジン全体の復旧ステータスに影響を与えます。デフォルト値は 0 で、リカバリが必要なときにすべてのリカバリ操作が実行されることを意味します (つまり、データ ページの検証/パージの取り消し/バッファ マージの挿入/ロールバック&フォワード)。エラーはログに記録されます。

innodb_force_recovery は 1 から 6 に設定でき、より大きな数値には以前のすべての数値の影響が含まれます。パラメーター値が 0 より大きい値に設定されている場合、テーブルに対して選択、作成、およびドロップ操作を実行できますが、挿入、更新、または削除などの操作は許可されません。

  • (SRV_FORCE_IGNORE_CORRUPT): チェック済みの破損ページを無視します。
  • (SRV_FORCE_NO_BACKGROUND): メイン スレッドが実行されないようにします。メイン スレッドが完全なパージ操作を実行する必要がある場合、クラッシュが発生します。
  • (SRV_FORCE_NO_TRX_UNDO): トランザクションのロールバック操作を実行しません。
  • (SRV_FORCE_NO_IBUF_MERGE): 挿入バッファーでマージ操作を実行しないでください。
  • (SRV_FORCE_NO_UNDO_LOG_SCAN): REDO ログを表示しないと、InnoDB ストレージ エンジンはコミットされていないトランザクションをコミット済みとして扱います。
  • (SRV_FORCE_NO_LOG_REDO): ロールフォワード操作を実行しません。

解決

一般的な修理方法の参考:

最初の方法

新しいテーブルを作成します。

create table demo_bak #和原表结构一样,只是把INNODB改成了MYISAM。

データのインポート

insert into demo_bak select * from demo;

元のテーブルを削除します。

drop table demo;

innodb_force_recovery をコメントアウトした後、再起動します。

名前を変更:

rename table demo_bak to demo;

最後に、ストレージ エンジンに戻ります。

alter table demo engine = innodb

2番目の方法

もう 1 つの方法は、mysqldump を使用してテーブルをエクスポートし、次に InnoDB テーブルにインポートすることです。両方の方法の結果は同じです。
バックアップ エクスポート (構造とデータを含む):

mysqldump -uroot -p123 test > test.sql

復元方法 1:

use test;
source test.sql

復元方法 2 (システム コマンド ライン):

mysql -uroot -p123 test < test.sql;

CHECK TABLE コマンドは基本的に InnoDB データベースでは役に立たないことに注意してください。

第三の方法

1.my.cnf を設定します

innodb_force_recovery = 1 または 2 - 6 の数字を設定し、MySQL を再起動します

2. データ スクリプトのエクスポート

mysqldump -uroot -p123 test > test.sql

SQL スクリプトをエクスポートします。または、Navicat を使用して、すべてのデータベース/テーブルを他のサーバーのデータベースにインポートします。

注: ここのデータは、正常にバックアップする必要があります。次に、元のデータベースのデータを削除します。

3. ib_logfile0、ib_logfile1、ibdata1 を削除します。

MySQL データ ディレクトリにある ib_logfile0、ib_logfile1、および ibdata1 の 3 つのファイルをバックアップし、これらの 3 つのファイルを削除します。

4. my.cnf を設定します

my.cnf の innodb_force_recovery = 1 または 2 ~ 6 の行構成を削除するか、innodb_force_recovery = 0 として構成し、MySQL サービスを再起動します。

5.MySQL データベースにデータをインポートする

mysql -uroot -p123 test < test.sql; 或者用Navicat将备份的数据导入到数据库中。

このアプローチで注意すべき問題:

  • 最初に ib_logfile0、ib_logfile1、および ibdata1 の 3 つのファイルをバックアップしてから削除する必要があります。
  • 元のデータのエクスポートが成功したことを必ず確認してください
  • データが正常にエクスポートされた後、元のデータベースのデータを削除するときに、データを削除できないというプロンプトが表示された場合は、コマンド ラインで MySQL データ ディレクトリを入力し、関連するデータベース フォルダまたはデータ テーブル ファイルを手動で削除できます。エクスポートまたはバックアップは成功しました。

 

フォローをクリックして、HUAWEI CLOUDの新技術について初めて学びましょう〜

{{o.name}}
{{m.name}}

おすすめ

転載: my.oschina.net/u/4526289/blog/5570405