MySQL-記一次備份失敗的排查過程
阿新 • • 發佈:2018-12-10
山竹來臨,窩在家裡整理個人文件。
本篇文章主要講解排查問題的思路,涉及linux 刪除檔案的原理、例項誤刪資料恢復、MySQL例項初始化引數優先級別等,雖然涉及知識點比較淺,但是個人覺得挺有意思的,所以翻出筆記釋出出來。
這個時候,可以初步確認,mysql 3307 初始化的時候,除了使用 指定的指令外,其他需要的啟動引數會從 預設的配置檔案路徑依次讀取。那麼,mysql 初始化需要讀取哪些 必備引數呢 ?
mysql 5.7 ,無預設配置檔案,僅指定引數 datadir basedir 初始化後生成 :mysql\sys\performance_schema 3個數據庫目錄及表格檔案,同時生成 ibdata1、ib_logfile[*]等檔案,是否可以判斷,初始化過程中,需要指定跟 ibdata1、ib_logfile【*】相關引數、error log位置、user 則正常呢?
/apps/svr/mysql57/bin/mysqld --initialize --datadir=/apps/dbdat/mysql57_data3307 --user=apps --innodb-data-file-path=ibdata1:1000M:autoextend --innodb-data-home-dir=/apps/dbdat/mysql57_data3307 --innodb-log-file-size=1000M --innodb-log-files-in-group=4 --basedir=/apps/svr/mysql57 --innodb_log_group_home_dir=/apps/dbdat/mysql57_data3307 --innodb-log-files-in-group=4 --log-error=/apps/logs/mysql/error3307.log 你以為這樣,就可以安裝了嗎? 並不,當存在預設路徑的配置檔案時,除了指定引數外,還是會去讀 預設路徑 上的配置檔案 為主。
1 備份出錯咯
測試環境測試 xtrabackup 相關效能的時候,備份失敗! 備份指令如下:1 innobackupex --defaults-file=/apps/conf/mysql/mysql5_3306.cnf --socket=/tmp/mysql3306.sock --user=[*]--password=[*] --no-timestamp /apps/mysql_backup/test_backup_1 > /apps/mysql_backup/backup.log 2>&1
備份錯誤日誌如下:
xtrabackup: The latest check point (for incremental): '1209962' xtrabackup: Stopping log copying thread. .xtrabackup: warning: Log block checksum mismatch (block no 2364 at lsn 1209856): expected 1161267116, calculated checksum 1312610971 xtrabackup: warning: this is possible when the log block has not been fully written by the server, will retry later.Tips: 資料庫例項執行正常的情況,在各個log buffer中,會存有 各個LSN,可以通過 show engine innodb status 檢視,但是注意,這個lsn並非是直接從磁碟檔案獲取,而是從buffer 中獲取。說明如下:180912 15:30:11 >> log scanned up to (1209856) 180912 15:30:11 Executing UNLOCK TABLES 180912 15:30:11 All tables unlocked 180912 15:30:11 Backup created in directory '/apps/mysql_backup/test_backup_1/' MySQL binlog position: filename 'mysql-bin.000001', position '26708128' 180912 15:30:11 [00] Writing /apps/mysql_backup/test_backup_1/backup-my.cnf180912 15:30:11 [00] ...done 180912 15:30:11 [00] Writing /apps/mysql_backup/test_backup_1/xtrabackup_info 180912 15:30:11 [00] ...done xtrabackup: Transaction log of lsn (1209962) to (1209856) was copied. xtrabackup: error: last checkpoint LSN (1209962) is larger than last copied LSN (1209856).
dba@localhost : (none) 17:00:21> show engine innodb status \G ...... --- LOG --- Log sequence number 4158179984 Log flushed up to 4158179984 Pages flushed up to 4158179984 Last checkpoint at 4158179975 0 pending log flushes, 0 pending chkp writes 128445 log i/o's done, 0.00 log i/o's/second ...... # Log sequence number: 當前系統最大的LSN號 # log flushed up to: 當前已經寫入redo日誌檔案的LSN # pages flushed up to:已經將更改寫入髒頁的lsn號 # Last checkpoint at:系統最後一次重新整理buffer pool髒中頁資料到磁碟的checkpoint
# LSN1 = Log sequence number
# LSN2 = log flushed up to
# LSN3 = pages flushed up to
# LSN4 = Last checkpoint at
# LSN1 >= LSN2 >= LSN3 >= LSN4
2 備份錯誤解讀
xtrabackup: error: last checkpoint LSN (1209962) is larger than last copied LSN (1209856).
說明xtrabckup 同步 redo log 到完成的時候,自身的 redo log 最後的 lsn 跟 當前資料庫的 ib_logfile檔案最後的 lsn對比,發現不匹配。
先檢查備份失敗例項內的 ib_logfile 檔案:
正常 ib_logfile 檔案的change time 應該是跟資料庫的初始化時間一致,因為沒有修改 檔案的許可權,但是顯示的change time 明顯晚與例項的執行時間,懷疑是否這幾個ib_logfile[*] 檔案被覆蓋! 為驗證ib_logfile[*] 檔案被覆蓋,檢查 mysql 程序下是否有 deleted 控制代碼,截圖如下,發現 ib_logfile[*]檔案確實被覆蓋。3 排查問題
哇,原來 檔案被刪除,這裡有幾個疑問 :- 為何檔案被刪除,不影響3306 例項 mysqld 的執行,3306 仍支援正常的 dml及ddl操作?
- 306的redo log 是寫入到哪些地方?
- 3306例項丟失的檔案能否恢復,能否正常使用?
- 為何 只有 redo log 檔案被刪除,是什麼操作導致?
3.1 檔案被刪,例項為何能正常執行
在linux中,每個檔案都有兩個 link 計數器:- i_count:檔案使用者或者被呼叫的數量,理解為記憶體引用的計數器。檔案被程序開啟使用的時候,自增+1。
- i_nlink:硬連結的數量,理解為磁碟引用計數器。建立檔案的硬連結的時候,自增+1。
3.2 資料實際寫入到哪裡,原被覆蓋檔案?proc檔案系統檔案?
測試2:刪除表格檔案,檢視控制代碼size是否變化? 測試內容:刪除ib_logfile0檔案及tbb.ibd檔案,往 tbb 表格插入資料,檢視 ib_logfile0大小及tbb.ibd大小 測試說明:為何是檢視大小,而不是檢視change time呢?因為node連結儲存了檔案的屬性,刪除了該連結,則無法檢視檔案屬性,僅能通過lsof檢視檔案大小來判斷寫入情況。/proc檔案系統中的 deleted 軟連線,stat檢視也是檢視軟連線的屬性,並非 真實檔案資料塊。無論是root還是其他使用者刪除,這個檔案都能寫入。 測試過程:見截圖 測試結果:因為ib_logfile 是固定大小1G,無法檢視到change時間,故不能驗證;但是可以從 tbb.ibd 檔案大小得知,實際是 redo log 是寫入到 被刪除的檔案的。3.3 恢復被刪除例項資料檔案
- 若是主庫檔案被刪
- 檢查從庫是否正常、是否無刪除檔案
- 從庫正常
- 方案1
- 主從切換
- 舊主上,根據deleted控制代碼重定向被刪除的資料塊到原先的磁碟位置,例: cat /proc/16979/fd/36 > /apps/dbdat/mysql5_data3306/sophia/tba.ibd
- 方案 2
- 重做 舊主庫,重做後恢復從庫使用
- 方案1
- 從庫不正常,檔案也被刪
- 從庫,停止複製
- 從庫,根據deleted控制代碼重定向被刪除的資料塊到原先的磁碟位置,例: cat /proc/16979/fd/36 > /apps/dbdat/mysql5_data3306/sophia/tba.ibd
- 從庫,恢復複製
- 檢查從庫追上主庫
- 主從切換
- 舊主新從,停止複製,重定向檔案內容 或者重做 從庫
- 從庫正常
- 檢查從庫是否正常、是否無刪除檔案
- 若是從庫檔案被刪
- 方案1
- 從庫停止複製
- 從庫上,根據deleted控制代碼重定向被刪除的資料塊到原先的磁碟位置,例: cat /proc/16979/fd/36 > /apps/dbdat/mysql5_data3306/sophia/tba.ibd
- 方案2
- 重做 舊主庫,重做後恢復從庫使用
- 方案1
3.4 為何僅ib_logfile[*]檔案被刪除,為何被刪
檢視 mysql 3306 的error 看看有啥苗頭:180912 15:09:51 [Note] Plugin 'FEDERATED' is disabled. 180912 15:09:51 InnoDB: The InnoDB memory heap is disabled 180912 15:09:51 InnoDB: Mutexes and rw_locks use GCC atomic builtins 180912 15:09:51 InnoDB: Compressed tables use zlib 1.2.3 180912 15:09:51 InnoDB: Using Linux native AIO 180912 15:09:51 InnoDB: Initializing buffer pool, size = 1.0G 180912 15:09:51 InnoDB: Completed initialization of buffer pool InnoDB: The first specified data file /apps/dbdat/mysql5_data3306/ibdata1 did not exist: InnoDB: a new database to be created! 180912 15:09:51 InnoDB: Setting file /apps/dbdat/mysql5_data3306/ibdata1 size to 1000 MB InnoDB: Database physically writes the file full: wait... InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 180912 15:09:55 InnoDB: Log file /apps/dbdat/mysql5_data3306/ib_logfile0 did not exist: new to be created InnoDB: Setting log file /apps/dbdat/mysql5_data3306/ib_logfile0 size to 1000 MB InnoDB: Database physically writes the file full: wait... InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 180912 15:09:58 InnoDB: Log file /apps/dbdat/mysql5_data3306/ib_logfile1 did not exist: new to be created InnoDB: Setting log file /apps/dbdat/mysql5_data3306/ib_logfile1 size to 1000 MB InnoDB: Database physically writes the file full: wait... InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 180912 15:10:01 InnoDB: Log file /apps/dbdat/mysql5_data3306/ib_logfile2 did not exist: new to be created InnoDB: Setting log file /apps/dbdat/mysql5_data3306/ib_logfile2 size to 1000 MB看log,是 新建例項的時候,覆蓋了 3306例項的 ib_logfile跟ibdata1,但是實際上為何只有 ib_logfile被覆蓋呢?檢視歷史 操作命令,找到了 初始化 例項的指令如下: history | grep mysql 368 /apps/svr/mysql57/bin/mysqld --initialize --datadir=/apps/dbdat/mysql57_data3307 --user=apps --innodb-data-file-path=ibdata1:1000M:autoextend --innodb-data-home-dir=/apps/dbdat/mysql57_data3307 --innodb-log-file-size=1000M --innodb-log-files-in-group=4
3.5 為何使用命令指定引數執行新建例項,會覆蓋其他例項的的檔案呢?
檢視history 操作時,發現 之前執行了了 初始化例項的指令,沒有指定 配置檔案,而是指定了 datadir,另起伺服器,執行該命令,是正常,截圖如下,那麼這裡又 引申了 第五個 問題:為何使用 命令執行新建例項,會覆蓋其他例項的的檔案呢? 靈機一動的我,聯想到了配置檔案的預設讀取順序,mysql安裝的時候,讀取配置檔案的優先順序:https://dev.mysql.com/doc/refman/5.7/en/option-files.html 。檢視 /etc/my.cnf ,發現確實是 有檔案存在,並且這個檔案是 3306的配置檔案內容。File Name | Purpose |
/etc/my.cnf | m |
/etc/mysql/my.cnf | Global options |
SYSCONFDIR/my.cnf | Global options |
$MYSQL_HOME/my.cnf | Server-specific options (server only) |
defaults-extra-file | |
~/.my.cnf | User-specific options |
~/.mylogin.cnf | User-specific login path options (clients only) |
/apps/svr/mysql57/bin/mysqld --initialize --datadir=/apps/dbdat/mysql57_data3307 --user=apps --innodb-data-file-path=ibdata1:1000M:autoextend --innodb-data-home-dir=/apps/dbdat/mysql57_data3307 --innodb-log-file-size=1000M --innodb-log-files-in-group=4 --basedir=/apps/svr/mysql57 --innodb_log_group_home_dir=/apps/dbdat/mysql57_data3307 --innodb-log-files-in-group=4 --log-error=/apps/logs/mysql/error3307.log 你以為這樣,就可以安裝了嗎? 並不,當存在預設路徑的配置檔案時,除了指定引數外,還是會去讀 預設路徑 上的配置檔案 為主。