-
簡介:
本文記錄刪除ibdata1 、ib_logfile 檔案被意外刪除且無法還原或損壞的解決方案,當刪除後沒有重啟mysql 可以查詢程序號,找到刪除的檔案可以還原回來。參考其他文章。本文介紹ibdata1 、ib_logfile 檔案無法找到或異常沒有備份的情況處理。
新安裝一臺mysql用作從庫
注意安裝版本與主庫版本一致。
獲取所有建表語句
如果原表所有建表語句都有儲存最方便直接用即可。
如果沒有儲存需要使用工具mysqlfrm。在問題機器主庫安裝下:
#安裝目錄 自己建立 cd /data/ #下載檔案 wget https://cdn.mysql.com/archives/mysql-utilities/mysql-utilities-1.6.5.tar.gz #解壓檔案 tar -xf mysql-utilities-1.6.5.tar.gz ls #進入解壓好的資料夾 cd mysql-utilities-1.6.5/ #build構建 python ./setup.py build #install安裝 python ./setup.py install #安裝成功檢視命令 mysqlfrm --version
- 模式介紹
–basedir:需指定伺服器的基本目錄,相當於再生一個資料庫例項,還需指定prot,user及.frm檔案位置等資訊,指定的prot不能與在執行的資料庫衝突,可在原資料庫無法開啟情況下使用,在讀取.frm檔案後,再生的例項將被關閉,所有的臨時檔案將被刪除。
例:mysqlfrm --basedir=/mysql/mysqld/ --port=3333 --user=mysql /mysql/data/test/tables.frm --show-stats
–server:需指定資料庫的連線字串,需在原資料庫可以開啟的情況下使用,指定資料庫使用者名稱,密碼,埠號及.frm檔案位置等資訊。
例:mysqlfrm --server=root:Root#123@localhost:3306 /mysql/data/test/tables.frm --port=3310 --user=mysql
注意:如資料庫還可以正常連線,推薦使用–server模式
- 獲取建表語句指令碼
#!/bin/bash # 定義變數 output_file="Create.sql" # 輸出檔名 mysql_root_password="123456" # MySQL root 使用者密碼 mysql_host="localhost" # MySQL 主機 mysql_port="3306" # MySQL 埠 mysql_user="mysql" # MySQL 使用者名稱 data_dir="/data/mysql/" # MySQL 資料目錄 excluded_dirs=(mysql sys performance_schema) # 需要排除的目錄列表 # 清空輸出檔案,如果檔案不存在則建立 > $output_file # 構建排除目錄的 find 過濾條件 exclude_find="" for dir in "${excluded_dirs[@]}"; do exclude_find+=" -path ${data_dir}${dir} -o" done exclude_find=${exclude_find::-2} # 去掉最後一個 "-o" # 查詢所有的 .frm 檔案,排除指定目錄 find $data_dir -type d \( $exclude_find \) -prune -o -type f -name '*.frm' -print | while read frm_file; do # 提取建表語句(去掉註釋) mysqlfrm --server=root:"$mysql_root_password"@$mysql_host:"$mysql_port" "$frm_file" --user=$mysql_user \ | grep -v '^#' >> $output_file echo -e "\n" >> $output_file # 新增換行符便於分隔 done echo "建表語句已儲存到 $output_file"
建表語句匯入從庫
從庫先建立所有主庫的庫,執行Create.sql語句。
還原資料
修改從庫配置檔案新增:innodb_force_recovery=1,重啟資料庫。
建表語句建立好後,對每個表進行刪除表空間,注意指令碼不要放mysql預設4個庫,指令碼如下:
#!/bin/bash # MySQL 使用者名稱和密碼 MYSQL_USER="root" MYSQL_PASS="123456" # 資料庫列表 databases=( "aaa" "bbbb" "ccc" "ddd" ) # 遍歷資料庫列表 for db in "${databases[@]}"; do echo "Processing database: $db" # 獲取當前資料庫中的所有表 tables=$(mysql -u $MYSQL_USER -p"$MYSQL_PASS" -e "SHOW TABLES;" $db | awk '{print $1}' | grep -v '^Tables_in') # 遍歷表列表並執行 DISCARD TABLESPACE for table in $tables; do echo "Discarding tablespace for table: $table in database: $db" mysql -u $MYSQL_USER -p$MYSQL_PASS -e "ALTER TABLE $table DISCARD TABLESPACE;" $db done done echo "Tablespace discard operation completed."
執行完刪除表空間後匯入主庫的ibd檔案。庫很多可以使用指令碼主庫打包mysql目錄放到從庫中,使用指令碼複製:
#!/bin/bash # 源目錄和目標目錄 src_dir="/home/mysqlbak" dest_dir="/home/mysql" # 目錄列表 dirs=( "aaa" "bbb" ) # 遍歷目錄列表並複製檔案 for dir in "${dirs[@]}"; do src_path="$src_dir/$dir" dest_path="$dest_dir/$dir" # 檢查源目錄是否存在 if [ -d "$src_path" ]; then # 複製 .ibd 檔案 if [ "$(ls -A $src_path/*.ibd 2>/dev/null)" ]; then echo "Copying .ibd files from $src_path to $dest_path" # 建立目標目錄(如果存在) if [ ! -d "$dest_path" ]; then echo "Directory $dest_path does not exist. Skipping copy." continue fi cp -a "$src_path"/*.ibd "$dest_path/" else echo "No .ibd files found in $src_path" fi else echo "Source directory $src_path does not exist" fi done echo "File copy operation completed."
再次執行匯入表空間命令,指令碼和刪除表空間基本一樣,複製一份修改一個地方即可:
mysql -u $MYSQL_USER -p$MYSQL_PASS -e "ALTER TABLE $table DISCARD TABLESPACE;" $db ##改為 mysql -u $MYSQL_USER -p$MYSQL_PASS -e "ALTER TABLE $table IMPORT TABLESPACE;" $db
大功告成!檢測從庫資料是否恢復。
資料恢復後注意修改配置檔案:innodb_force_recovery=1 刪除,重啟資料庫。