MySQL數據庫備份和遷移,是DBA日常工作中,經常需要做的工作。備份一般由物理備份和邏輯備份兩種,對於用xtrabackup進行物理備份來說,表數據和用戶權限都會全部備份和恢復;如果是邏輯備份的話,用戶數據和授權信息都需要單獨的導出導入,用戶數據直接用 mysqldump 工具導出導入即可,但mysql中用戶權限不能直接導出導入,一個權限一個權限的處理,有比較麻煩。
所以編寫一個mysql用戶權限腳本,對源數據庫中的用戶授權信息進行導出,就非常必要了。只要有用戶權限的授權sql,不論是平時備份,還是遷移時授權,都會很有用處。
mysql用戶權限的獲取,整體可以從mysql.user表來獲取用戶的相關權限來生成相應的SQL語句,然後在目標服務器上來執行生成的SQL語句即可。
1、創建導出用戶權限的腳本
在源服務器上,創建一個用於導出用戶權限的exp_grants.sh 腳本,腳本內容如下:
#!/bin/bash #Function export user privileges source /etc/profile pwd=123456 expgrants() { mysql -B -u'root' -p${pwd} -N -S /data/mysql_3306/tmp/mysql.sock $@ -e "SELECT CONCAT( 'SHOW GRANTS FOR ''', user, '''@''', host, ''';' ) AS query FROM mysql.user" | \ mysql -u'root' -p${pwd} -S /data/mysql_3306/tmp/mysql.sock $@ | \ sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/-- \1 /;/--/{x;p;x;}' } expgrants > ./grants.sql
這個導出腳本的整體思路是:分成三個步驟,用管道連接起來,前一步操作的結果,作爲後一步操作的輸入:
第一步先使用concat函數,查詢mysql.user中的用戶授權,並連接成一個show grants for 命令,執行命令時,加上 "-B -N"選項,讓輸出結果沒有列名和方框,只是命令;
第二步將上一步的show grants for 命令,再次執行一次,得出mysql中每個授權對應的具體的GRANT授權命令;
第三步使用sed和正則表達式,將上一步的運行結果進行處理,在show grant for 行中加上註釋前綴和一個空行,在具體授權的GRANT行中結尾加一個分號,形成可以執行的sql授權命令。
其中正則表達式添加和修改如下,紅色爲選擇行條件,紫色爲添加和修改的內容:
sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/-- \1 /;/--/{x;p;x;}'
2、在源服務器上執行上面腳本,生成授予權限的SQL腳本
# ./exp_grants.sh
# cat grants.sql
上面兩個步驟在我的測試環境中執行過程爲:
[root@test07 tmp]# > grants.sql [root@test07 tmp]# [root@test07 tmp]# [root@test07 tmp]# cat exp_grants.sh #!/bin/bash #Function export user privileges source /etc/profile pwd=123456 expgrants() { mysql -B -u'root' -p${pwd} -N -S /data/mysql_3306/tmp/mysql.sock $@ -e "SELECT CONCAT( 'SHOW GRANTS FOR ''', user, '''@''', host, ''';' ) AS query FROM mysql.user" | \ mysql -u'root' -p${pwd} -S /data/mysql_3306/tmp/mysql.sock $@ | \ sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/-- \1 /;/--/{x;p;x;}' } expgrants > ./grants.sql [root@test07 tmp]# [root@test07 tmp]# [root@test07 tmp]# ./exp_grants.sh [root@test07 tmp]# [root@test07 tmp]# [root@test07 tmp]# cat grants.sql -- Grants for [email protected] GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' WITH GRANT OPTION; -- Grants for [email protected].%.% GRANT USAGE ON *.* TO 'wgphp'@'192.168.%.%'; GRANT SELECT, INSERT, UPDATE, EXECUTE ON `test`.* TO 'wgphp'@'192.168.%.%'; -- Grants for [email protected] GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.226.163' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9'; -- Grants for [email protected] GRANT USAGE ON *.* TO 'test'@'192.168.226.163' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `test04`.* TO 'test'@'192.168.226.163'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `test03`.* TO 'test'@'192.168.226.163'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `test01`.* TO 'test'@'192.168.226.163'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `test02`.* TO 'test'@'192.168.226.163'; -- Grants for root@::1 GRANT ALL PRIVILEGES ON *.* TO 'root'@'::1' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' WITH GRANT OPTION; -- Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' WITH GRANT OPTION; GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION; -- Grants for test@localhost GRANT USAGE ON *.* TO 'test'@'localhost' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `test04`.* TO 'test'@'localhost'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `test01`.* TO 'test'@'localhost'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `test02`.* TO 'test'@'localhost'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `test03`.* TO 'test'@'localhost'; [root@test07 tmp]#
3、在目標服務器上執行授予權限的SQL腳本,進行授權
將生成的腳本在目標服務器上執行即可,:
mysql -uname -ppwd < grants.sql
或者先登錄到mysql客戶端,在用source命令執行:
mysql -uname -ppwd -S /data/mysql_3306/tmp/mysql.sock
mysql> source /tmp/grants.sql
mysql> flush privileges;
需要注意:
a、目標服務上爲非空服務器,已經存在一些賬戶及權限應考慮會覆蓋的問題。
b、如果僅僅需要遷移非root用戶,可以在原腳本中添加過濾條件,即 where user<>'root' 。
c、由於測試環境中mysql的端口、socket、用戶密碼等不一定是默認配置,mysql連接時需要根據情況修改。
d、第三步在目標服務器上執行了授予權限的sql腳本後,記得要執行 flush privileges; 才能夠讓授權生效。
第三步的測試過程爲:
[root@test07 tmp]# [root@test07 tmp]# [root@test07 tmp]# mysql -B -u'root' -p123456 -N -S /data/mysql_3306/tmp/mysql.sock -e "select user,host from mysql.user;" root 127.0.0.1 wgphp 192.168.%.% root 192.168.226.163 test 192.168.226.163 root ::1 root localhost test localhost [root@test07 tmp]# [root@test07 tmp]# mysql -u'root' -p123456 -S /data/mysql_3306/tmp/mysql.sock -e "select user,host from mysql.user;" +-------+-----------------+ | user | host | +-------+-----------------+ | root | 127.0.0.1 | | wgphp | 192.168.%.% | | root | 192.168.226.163 | | test | 192.168.226.163 | | root | ::1 | | root | localhost | | test | localhost | +-------+-----------------+ [root@test07 tmp]# [root@test07 tmp]# mysql -u'root' -p123456 -S /data/mysql_3306/tmp/mysql.sock -e "delete from mysql.user where user<>'root';select user,host from mysql.user;" +------+-----------------+ | user | host | +------+-----------------+ | root | 127.0.0.1 | | root | 192.168.226.163 | | root | ::1 | | root | localhost | +------+-----------------+ [root@test07 tmp]# [root@test07 tmp]# [root@test07 tmp]# mysql -u'root' -p123456 -S /data/mysql_3306/tmp/mysql.sock < /tmp/grants.sql [root@test07 tmp]# [root@test07 tmp]# mysql -u'root' -p123456 -S /data/mysql_3306/tmp/mysql.sock -e "flush privileges;select user,host from mysql.user;" +-------+-----------------+ | user | host | +-------+-----------------+ | root | 127.0.0.1 | | wgphp | 192.168.%.% | | root | 192.168.226.163 | | test | 192.168.226.163 | | root | ::1 | | root | localhost | | test | localhost | +-------+-----------------+