近期,測試環境出現了一次MySQL資料庫不斷自動重啟的問題,導致的原因是強行kill -9 殺掉資料庫程式導致,報錯資訊如下:
2019-07-24T01:14:53.769512Z 0 [Note] Executing 'SELECT * FROM INFORMATION_SCHEMA.TABLES;' to get a list of tables using the deprecated partition engine. You may use the startup option '--disable-partition-engine-check' to skip this check. 2019-07-24T01:14:53.769516Z 0 [Note] Beginning of list of non-natively partitioned tables 01:14:53 UTC - mysqld got signal 11 ; 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. Attempting to collect some information that could help diagnose the problem. As this is a crash and something is definitely wrong, the information collection process might fail. Please help us make Percona Server better by reporting any bugs at http://bugs.percona.com/ key_buffer_size=33554432 read_buffer_size=8388608 max_used_connections=0 max_threads=501 thread_count=4 connection_count=0 It is possible that mysqld could use up to key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 4478400 K bytes of memory Hope that's ok; if not, decrease some variables in the equation. Thread pointer: 0x7f486900e000 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 = 7f4846172820 thread_stack 0x80000 /usr/local/mysql5.7/bin/mysqld(my_print_stacktrace+0x2c)[0xed481c] /usr/local/mysql5.7/bin/mysqld(handle_fatal_signal+0x461)[0x7a15a1] /lib64/libpthread.so.0(+0xf7e0)[0x7f498697c7e0] /usr/local/mysql5.7/bin/mysqld(_ZN12ha_federated7rnd_posEPhS0_+0x2f)[0x12bcc3f] /usr/local/mysql5.7/bin/mysqld(_ZN7handler10ha_rnd_posEPhS0_+0x172)[0x804a12] /usr/local/mysql5.7/bin/mysqld(_ZN14Rows_log_event24do_index_scan_and_updateEPK14Relay_log_info+0x1e3)[0xe50e23] /usr/local/mysql5.7/bin/mysqld(_ZN14Rows_log_event14do_apply_eventEPK14Relay_log_info+0x716)[0xe50196] /usr/local/mysql5.7/bin/mysqld(_ZN9Log_event11apply_eventEP14Relay_log_info+0x6e)[0xe48fde] /usr/local/mysql5.7/bin/mysqld(_Z26apply_event_and_update_posPP9Log_eventP3THDP14Relay_log_info+0x1f0)[0xe8d6f0] /usr/local/mysql5.7/bin/mysqld(handle_slave_sql+0x163d)[0xe9a0fd] /usr/local/mysql5.7/bin/mysqld(pfs_spawn_thread+0x1b4)[0x1209414] /lib64/libpthread.so.0(+0x7aa1)[0x7f4986974aa1] /lib64/libc.so.6(clone+0x6d)[0x7f4984c6bc4d] Trying to get some variables. Some pointers may be invalid and cause the dump to abort. Query (0): is an invalid pointer Connection ID (thread ID): 2 Status: NOT_KILLED You may download the Percona Server operations manual by visiting http://www.percona.com/software/percona-server/. You may find information in the manual which will help you identify the cause of the crash.
1. 初探過程
之前出現過類似的情況時,是因為記憶體不足,因日誌中也有對應的提示:
key_buffer_size=33554432 read_buffer_size=8388608 max_used_connections=0 max_threads=501 thread_count=4 connection_count=0 It is possible that mysqld could use up to key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 4478400 K bytes of memory Hope that's ok; if not, decrease some variables in the equation.
此測試環境實體記憶體確實不大,且剩餘記憶體也不足,而且是作為另一個測試環境的從庫,記憶體分配的也少。
之前一些環境也出現過類似的情況,通過調整引數及釋放記憶體的等處理後可以正常啟動,於是嘗試著關閉一些臨時程式並調整MySQL上述幾個引數的值,如:
[mysqld] max_connections = 50
然後重新啟動MySQL,結果依舊不斷重啟。
初步處理未果。
2. 新增innodb_force_recovery 解決不斷重啟
在配置檔案my.cnf新增innodb_force_recovery 先處理不斷重啟的問題
[mysqld] innodb_force_recovery = 4
新增後,再次啟動MySQL,此時不再出現反覆重啟。
檢視資料庫日誌,有提示 [Note] InnoDB: !!! innodb_force_recovery is set to 4 !!!如下:
因為此時可以開啟資料庫,於是嘗試啟動從庫,但是此時報錯,提示Table 'mysql.slave_relay_log_info' is read only.
此時再看錯誤日誌,如下
因此,本次啟動時,innodb_force_recovery 設定為 4,在MySQL 5.6.15 以後,當 innodb_force_recovery 的值大於等於 4 的時候,InnoDB 表處於只讀模式,因啟動複製時需要將資訊寫入表中,所以此時報錯。
注: 因設定為1-3 時,依舊未生效,因此我在處理時設定的為4(4 以上的值可能永久導致資料檔案損壞。如果生產環境出現類似問題務必先拷貝一份測試,在測試通過後再在生產環境處理)。此時可以將所有資料dump出,之後再恢復即可。
3. innodb_force_recovery 引數
innodb_force_recovery 可以設定為 1-6,大的值包含前面所有小於它的值的影響。
1 (SRV_FORCE_IGNORE_CORRUPT): 忽略檢查到的 corrupt 頁。儘管檢測到了損壞的 page 仍強制服務執行。一般設定為該值即可,然後 dump 出庫表進行重建。 2 (SRV_FORCE_NO_BACKGROUND): 阻止主執行緒的執行,如主執行緒需要執行 full purge 操作,會導致 crash。 阻止 master thread 和任何 purge thread 執行。若 crash 發生在 purge 環節則使用該值。 3 (SRV_FORCE_NO_TRX_UNDO): 不執行事務回滾操作。 4 (SRV_FORCE_NO_IBUF_MERGE): 不執行插入緩衝的合併操作。如果可能導致崩潰則不要做這些操作。不要進行統計操作。該值可能永久損壞資料檔案。若使用了該值,則將來要刪除和重建輔助索引。 5 (SRV_FORCE_NO_UNDO_LOG_SCAN): 不檢視重做日誌,InnoDB 儲存引擎會將未提交的事務視為已提交。此時 InnoDB 甚至把未完成的事務按照提交處理。該值可能永久性的損壞資料檔案。 6 (SRV_FORCE_NO_LOG_REDO): 不執行前滾的操作。恢復時不做 redo log roll-forward。使資料庫頁處於廢止狀態,繼而可能引起 B 樹或者其他資料庫結構更多的損壞。
注意:
- 為了安全,當設定引數值大於 0 後,可以對錶進行 select, create, drop 操作,但 insert, update 或者 delete 這類操作是不允許的。
- MySQL 5.6.15 以後,當 innodb_force_recovery 的值大於等於 4 的時候,InnoDB 表處於只讀模式。
- 在值小於等於 3 時可以通過 select 來 dump 表,可以 drop 或者 create 表。
- MySQL 5.6.27 後大於 3 的值也支援 DROP TABLE; 如果事先知道哪個表導致了崩潰則可 drop 掉這個表。
- 如果碰到了由失敗的大規模匯入或大量 ALTER TABLE 操作引起的 runaway rollback,則可 kill 掉 mysqld 執行緒然後設定 innodb_force_recovery = 3 使資料庫重啟後不進行 rollback。然後刪除導致 runaway rollback 的表; 如果表內的資料損壞導致不能 dump 整個表內容。那麼附帶 order by primary_key desc 從句的查詢或許能夠 dump 出損壞部分之後的部分資料;
耿小廚已開通個人微信公眾號,想進一步溝通或想了解其他文章的同學可以關注我