技術交流群總是能帶來很多實際生產環境遇到的問題,例如,近期就有人遇到user表內容被清空的情況。如果發生了此情況,千萬不要慌,更不能隱瞞問題(今天這位朋友就比較慘,別人刪了也沒敢告知,結果binlog已經清理了),這樣有利於恢復。現在針對幾種情況,進行恢復操作的演示。
1. user表內容被清空
如果有權限的同學誤執行了情況mysql.user表內容的情況,如果是delete的方式還是相對容易恢復的(binlog存在的情況)
1.1 模擬誤刪除
/* 當前user表的內容 */ mysql> select user,host from mysql.user; +---------------+--------------+ | user | host | +---------------+--------------+ | repl | 192.168.28.% | | mysql.session | localhost | | mysql.sys | localhost | | root | localhost | +---------------+--------------+ 4 rows in set (0.00 sec) mysql> select now(); +---------------------+ | now() | +---------------------+ | 2020-04-16 06:37:07 | +---------------------+ 1 row in set (0.00 sec)
現在執行誤刪除
mysql> delete from mysql.user; Query OK, 4 rows affected (0.01 sec) mysql>
1.2 恢復
當前情況下,如開啟了binlog(生產環境一般都是開啟了的),則可以從binlog恢復
注意如果有全部及其之后的binlog 則可以通過恢復備份並追加binlog的方式恢復數據(后續其他文章再專題介紹),本文基於無全備,僅有最近的日志情況下恢復(主要是為了使用binlog2sql工具)
1.2.1 先恢復root賬號
因為刪除后,其他用戶無法重新連接數據庫了,需要緊急恢復root賬號,再做后續其他賬號的恢復,恢復步驟為:
修改為跳過授權的模式,即在配置文件my.cnf文件中添加 skip-grant-tables
重啟數據庫
登錄數據庫,添加root@'localhost'賬號(可以從相同版本數據庫中導出一個root賬號的sql語句恢復
/usr/local/mysql5.7/bin/mysqldump -uroot -p'123456' -t --socket=/data/mysql3307/tmp/mysql.sock mysql user --where " 1=1 and user='root' and host='localhost'" >1.sql
恢復數據
mysql> use mysql; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> INSERT INTO `user` VALUES ('localhost','root','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password',password('123456'),'N',now(),NULL,'N'); Query OK, 1 row affected (0.01 sec)
改為授權模式: 將配置文件里的 skip-grant-tables 注釋或刪除
再次重啟數據庫即可用剛恢復的root賬號登錄了
mysql> select user,host from mysql.user; +------+-----------+ | user | host | +------+-----------+ | root | localhost | +------+-----------+ 1 row in set (0.00 sec)
注: 如果清空數據或后續說的刪除了user表后沒有退出當前會話,就無需之前的修改參數及重啟數據庫了,可以直接先從其他實例中先恢復root賬號。
1.2.2 安裝binlog2sql
binlog2sql依賴python2.7及以上版本,且依賴包通過pip安裝,對於python的升級及pip的安裝可參考歷史文章
yum install -y git wget git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
1.2.3 使用binlog2sql工具恢復數據
使用binlog2sql的閃回工具將刪除解析處理生成一個insert的sql腳本
python binlog2sql.py --flashback -h localhost -u root -p 123456 -d mysql -t user --start-file='mysql-bin.000002' --start-datetime='2020-04-16 06:37:07' --stop-datetime='2020-04-16 06:40:00' >mysql.sql
將數據導入mysql.user表即可。
注: 其他用法請參考https://github.com/danfengcao/binlog2sql
2. user 表被drop
2.1 模擬user 表被drop
mysql> drop table mysql.user; Query OK, 0 rows affected (0.01 sec)
2.2 恢復
2.2.1 恢復表結構
表結構的恢復比較簡單,可以從其他相同版本的數據庫里復制user表的建表語句,然后導入即可
CREATE TABLE `user` ( `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', `User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '', `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', `ssl_cipher` blob NOT NULL, `x509_issuer` blob NOT NULL, `x509_subject` blob NOT NULL, `max_questions` int(11) unsigned NOT NULL DEFAULT '0', `max_updates` int(11) unsigned NOT NULL DEFAULT '0', `max_connections` int(11) unsigned NOT NULL DEFAULT '0', `max_user_connections` int(11) unsigned NOT NULL DEFAULT '0', `plugin` char(64) COLLATE utf8_bin NOT NULL DEFAULT 'mysql_native_password', `authentication_string` text COLLATE utf8_bin, `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `password_last_changed` timestamp NULL DEFAULT NULL, `password_lifetime` smallint(5) unsigned DEFAULT NULL, `account_locked` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (`Host`,`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
2.2.2 恢復數據
drop的方式刪除數據后無法直接通過之前的binlog閃回恢復了,需要依賴於全備來恢復,關於備份恢復可以參考以下文章來恢復,此處不再贅述
3. 小結
對於刪除表后的恢復其實不止以上這些方式,另外還可以通過操作系統級別進行恢復,但各種恢復方式均和實際場景有關,希望大家也自行探索或多參與技術交流,提高自己的技能水平。
想了解更多內容或參與技術交流可以關注微信公眾號 數據庫干貨鋪 入群溝通。