據(jù)目錄修改與遷移實(shí)戰(zhàn):從datadir配置到避坑指南)
1. 為什么MySQL數(shù)據(jù)目錄成了很多人繞不過(guò)去的坑先說(shuō)一個(gè)真實(shí)的場(chǎng)景很多人在用MySQL的時(shí)候一開(kāi)始都是在本地測(cè)試環(huán)境裝好就完事數(shù)據(jù)默認(rèn)丟在安裝目錄下的data文件夾里。等到項(xiàng)目上線、數(shù)據(jù)文件開(kāi)始漲到幾十個(gè)G甚至上百G的時(shí)候才發(fā)現(xiàn)系統(tǒng)盤空間不夠了這時(shí)候才急著想把數(shù)據(jù)目錄挪到數(shù)據(jù)盤上。如果之前沒(méi)有仔細(xì)規(guī)劃過(guò)這個(gè)遷移過(guò)程往往伴隨著停機(jī)、權(quán)限報(bào)錯(cuò)、SELinux攔截、服務(wù)起不來(lái)等各種問(wèn)題稍微處理不好寶貴的數(shù)據(jù)就可能面臨風(fēng)險(xiǎn)。這個(gè)主題適合所有在用MySQL的人不管你是剛裝好MySQL想規(guī)劃目錄結(jié)構(gòu)的新手還是已經(jīng)在生產(chǎn)環(huán)境里碰到磁盤告警、準(zhǔn)備做數(shù)據(jù)目錄遷移的運(yùn)維同學(xué)這篇文章的內(nèi)容都值得你花幾分鐘看懂。我會(huì)從MySQL數(shù)據(jù)目錄的基本概念出發(fā)講清楚為什么要改目錄、怎么查看當(dāng)前數(shù)據(jù)目錄、三種常用的修改方式以及我在實(shí)際環(huán)境中踩過(guò)的那些坑和總結(jié)出的排查思路。MySQL作為目前最流行的開(kāi)源關(guān)系型數(shù)據(jù)庫(kù)之一它的數(shù)據(jù)存儲(chǔ)機(jī)制其實(shí)并不復(fù)雜所有數(shù)據(jù)庫(kù)、表、索引、日志等文件最終都以文件的形式落在操作系統(tǒng)的一個(gè)固定目錄下這個(gè)目錄在MySQL里叫datadir。默認(rèn)情況下Linux發(fā)行版通過(guò)包管理器安裝的MySQL或者M(jìn)ariaDB數(shù)據(jù)目錄一般在/var/lib/mysql而Windows下用安裝包裝的MySQL默認(rèn)數(shù)據(jù)目錄通常在C:\ProgramData\MySQL\MySQL Server 8.0\Data。生產(chǎn)環(huán)境里系統(tǒng)盤和數(shù)據(jù)盤分開(kāi)是標(biāo)配數(shù)據(jù)目錄放系統(tǒng)盤既不安全也容易爆盤所以學(xué)會(huì)修改數(shù)據(jù)目錄幾乎是每個(gè)MySQL使用者都繞不開(kāi)的基本功。2. 核心概念MySQL數(shù)據(jù)目錄里到底放了什么2.1 datadir參數(shù)的含義與作用范圍datadir是MySQL服務(wù)器的核心參數(shù)之一它定義了所有數(shù)據(jù)庫(kù)文件存放的根路徑。你可以用下面這條SQL直接查看當(dāng)前的設(shè)置SHOW VARIABLES LIKE datadir;我以前在排查問(wèn)題的時(shí)候發(fā)現(xiàn)不少同事其實(shí)對(duì)datadir的理解比較模糊他們以為數(shù)據(jù)目錄就是某個(gè)數(shù)據(jù)庫(kù)的文件夾其實(shí)不是。datadir是整個(gè)MySQL實(shí)例存放所有數(shù)據(jù)的根目錄在這個(gè)根目錄下你會(huì)看到每個(gè)數(shù)據(jù)庫(kù)對(duì)應(yīng)一個(gè)子目錄比如mysql、sys、你自己創(chuàng)建的庫(kù)除此之外還有一些全局文件包括ibdata1系統(tǒng)表空間存放數(shù)據(jù)字典、undo log等、ib_logfile0和ib_logfile1redo log8.0.30版本之后默認(rèn)使用#innodb_redo目錄、undo_001和undo_002undo log文件、binlog.000001等二進(jìn)制日志文件如果開(kāi)啟了binlog以及auto.cnf服務(wù)器UUID和mysql.ibd數(shù)據(jù)字典表空間等。理解了這個(gè)結(jié)構(gòu)你會(huì)發(fā)現(xiàn)一個(gè)很關(guān)鍵的點(diǎn)datadir不只是某一個(gè)庫(kù)的數(shù)據(jù)它是整個(gè)MySQL實(shí)例的“家”。所以修改數(shù)據(jù)目錄本質(zhì)上不是“把庫(kù)目錄搬走”而是“給整個(gè)實(shí)例搬家”這就決定了遷移過(guò)程必須非常謹(jǐn)慎不能只拷貝業(yè)務(wù)庫(kù)目錄就完事。2.2 默認(rèn)目錄與初始化流程的關(guān)聯(lián)MySQL在初始化實(shí)例的時(shí)候會(huì)把系統(tǒng)數(shù)據(jù)庫(kù)mysql、performance_schema、sys等和各種基礎(chǔ)表創(chuàng)建到datadir指定的目錄里。如果你用的是發(fā)行版自帶的包管理器安裝比如CentOS的yum、Ubuntu的apt安裝完成后服務(wù)啟動(dòng)時(shí)會(huì)自動(dòng)執(zhí)行初始化腳本默認(rèn)路徑就是/var/lib/mysql。這里有個(gè)比較容易出問(wèn)題的地方有些人在安裝MySQL 8.0后直接修改my.cnf里的datadir路徑然后重啟服務(wù)結(jié)果服務(wù)起不來(lái)報(bào)錯(cuò)信息是找不到mysql.ibd或者ibdata1。原因很簡(jiǎn)單——你改了配置文件但新路徑下根本沒(méi)有初始化的數(shù)據(jù)文件。MySQL的啟動(dòng)邏輯是先讀配置拿到datadir然后到這個(gè)目錄下去找系統(tǒng)表空間和數(shù)據(jù)字典找不到就直接啟動(dòng)失敗而不是自動(dòng)幫你初始化。所以修改數(shù)據(jù)目錄有兩種完全不同的場(chǎng)景一種是在安裝完成后、初始化前就指定好目錄另一種是已經(jīng)跑了一段時(shí)間需要把現(xiàn)有數(shù)據(jù)完整遷移過(guò)去。這兩種場(chǎng)景的操作步驟不一樣后面我會(huì)分別講清楚。2.3 8.0版本相比5.7有哪些需要特別注意的差異如果你是從MySQL 5.7遷到8.0或者直接在8.0上做目錄修改有幾個(gè)差異點(diǎn)必須心里有數(shù)第一MySQL 8.0的數(shù)據(jù)字典是集中管理的存儲(chǔ)在mysql.ibd中不再像5.7那樣每個(gè)表都有一個(gè).frm文件。這意味著8.0對(duì)數(shù)據(jù)目錄的完整性要求更高如果拷貝數(shù)據(jù)時(shí)漏了文件啟動(dòng)時(shí)報(bào)錯(cuò)會(huì)更早、更隱蔽。第二8.0.30版本開(kāi)始redo log默認(rèn)存放在#innodb_redo這個(gè)子目錄里而不再是以ib_logfile0、ib_logfile1這種平鋪文件的形式存在。遷移數(shù)據(jù)時(shí)這個(gè)目錄也要一并拷貝。第三8.0在初始化方式和密碼策略上也有變化mysql_install_db腳本在官方壓縮包中不再提供統(tǒng)一使用mysqld --initialize來(lái)初始化。這直接影響你在修改數(shù)據(jù)目錄后如何生成初始數(shù)據(jù)文件。這些差異如果你不了解很容易在網(wǎng)上搜到5.7時(shí)代的教程照著操作卻發(fā)現(xiàn)行不通白白浪費(fèi)時(shí)間。3. 動(dòng)手之前梳理三種修改數(shù)據(jù)目錄的常見(jiàn)思路3.1 直接修改my.cnf配置文件這是最直觀的思路編輯MySQL的配置文件Linux下一般是/etc/my.cnf或者/etc/mysql/my.cnf在[mysqld]段下修改datadir參數(shù)然后重啟服務(wù)。[mysqld] datadir/data/mysql但這里有一個(gè)隱含前提/data/mysql這個(gè)目錄必須已經(jīng)存在并且里面必須有完整的、可用的數(shù)據(jù)文件。如果目錄是空的MySQL是啟動(dòng)不起來(lái)的。所以“直接修改配置”這句話通常只是整個(gè)流程的最后一步前面還得做初始化或者數(shù)據(jù)拷貝。這種方式的優(yōu)點(diǎn)是簡(jiǎn)單直接、配置路徑清晰適合新裝環(huán)境缺點(diǎn)是一旦數(shù)據(jù)目錄已經(jīng)存有數(shù)據(jù)光改配置是不夠的還需要做遷移。3.2 通過(guò)遷移方式把原數(shù)據(jù)整體搬走遷移方式適用于已經(jīng)運(yùn)行了一段時(shí)間的MySQL實(shí)例操作核心是先停服務(wù)把原datadir下的所有文件原樣拷貝到新目錄再修改配置指向新目錄最后啟動(dòng)服務(wù)驗(yàn)證。這種方式的優(yōu)點(diǎn)是你的數(shù)據(jù)文件、權(quán)限、目錄結(jié)構(gòu)都是現(xiàn)成的只要拷貝完整基本不會(huì)出問(wèn)題缺點(diǎn)是拷貝大文件耗時(shí)較長(zhǎng)期間服務(wù)需要停機(jī)。很多人會(huì)問(wèn)能不能不拷貝直接用ln -s軟鏈接把新目錄鏈接到原路徑我在實(shí)際中也試過(guò)確實(shí)可以但MySQL官方并不推薦在生產(chǎn)環(huán)境這么做因?yàn)檐涙溄訒?huì)讓目錄結(jié)構(gòu)變得不透明后續(xù)做備份、升級(jí)、排查問(wèn)題時(shí)很容易繞暈。除非你的環(huán)境非常特殊否則還是老老實(shí)實(shí)做數(shù)據(jù)遷移吧。3.3 通過(guò)初始化新環(huán)境再導(dǎo)入數(shù)據(jù)這種方式等于重建一個(gè)全新的MySQL實(shí)例把datadir指定到新目錄初始化完成后再把舊庫(kù)的數(shù)據(jù)通過(guò)邏輯備份mysqldump或物理備份的方式導(dǎo)入到新庫(kù)。適合跨大版本遷移比如5.7升8.0、操作系統(tǒng)更換、或者你想順便做一次數(shù)據(jù)清理的場(chǎng)景。優(yōu)點(diǎn)是不用關(guān)心底層文件格式是否兼容8.0和5.7的物理文件結(jié)構(gòu)差異很大不能直接拷貝缺點(diǎn)是需要停機(jī)、導(dǎo)入時(shí)間可能很長(zhǎng)、而且要人工介入的地方多操作風(fēng)險(xiǎn)也不小。一句話總結(jié)小數(shù)據(jù)量、正常停機(jī)窗口內(nèi)能完成拷貝的選方案2跨版本遷移或者數(shù)據(jù)量特別大、拷貝時(shí)間遠(yuǎn)大于導(dǎo)入時(shí)間的選方案3全新環(huán)境安裝直接改配置加初始化即可。4. 實(shí)操全流程以Linux環(huán)境MySQL 8.0為例完整走一遍4.1 第一步確認(rèn)當(dāng)前狀態(tài)和數(shù)據(jù)量動(dòng)手之前先把現(xiàn)狀查清楚。我一般依次執(zhí)行這幾條命令# 查看MySQL當(dāng)前的數(shù)據(jù)目錄 mysql -uroot -p -e SHOW VARIABLES LIKE datadir; # 查看各數(shù)據(jù)庫(kù)占用空間便于規(guī)劃新目錄容量 du -sh /var/lib/mysql/* # 查看磁盤分區(qū)情況 df -h這一步的目標(biāo)很明確知道原數(shù)據(jù)有多大、新目標(biāo)分區(qū)有沒(méi)有足夠的空間、當(dāng)前配置文件在哪個(gè)路徑、服務(wù)是怎么啟動(dòng)的systemd還是init腳本。很多時(shí)候遷移失敗都是因?yàn)榍捌跊](méi)查清楚就直接操作結(jié)果做到一半發(fā)現(xiàn)目標(biāo)盤空間不夠進(jìn)退兩難。接著還要確認(rèn)配置文件的位置和生效順序。MySQL讀取配置文件的順序非常容易忽略它依次讀取/etc/my.cnf、/etc/mysql/my.cnf、~/.my.cnf等后面的配置會(huì)覆蓋前面的不同發(fā)行版還不太一樣。我習(xí)慣用下面這個(gè)命令確認(rèn)最終生效的配置從哪里來(lái)的mysqld --verbose --help | grep -A 1 Default options這個(gè)命令會(huì)直接告訴你當(dāng)前mysqld會(huì)讀取哪些配置文件順序是什么非常直觀。4.2 第二步規(guī)劃新目錄與權(quán)限設(shè)置假設(shè)我們要把數(shù)據(jù)目錄遷到/data/mysql首先要?jiǎng)?chuàng)建目錄、歸屬給mysql用戶mkdir -p /data/mysql chown -R mysql:mysql /data/mysql chmod 750 /data/mysql這里有兩個(gè)容易踩坑的點(diǎn)。第一目錄權(quán)限。MySQL服務(wù)通常以mysql系統(tǒng)用戶運(yùn)行新目錄必須讓這個(gè)用戶有完全讀寫(xiě)權(quán)限否則啟動(dòng)時(shí)會(huì)報(bào)Permission denied。我建議權(quán)限直接設(shè)750所有者和組都設(shè)為mysql這樣既安全又不會(huì)出問(wèn)題。有的教程會(huì)讓你chmod 777生產(chǎn)環(huán)境千萬(wàn)別這么干數(shù)據(jù)目錄對(duì)任何其他用戶開(kāi)放是完全不可接受的。第二SELinux。很多CentOS環(huán)境默認(rèn)開(kāi)著SELinux就算你目錄權(quán)限完全正確MySQL也可能因?yàn)镾ELinux策略攔截而無(wú)法讀取新目錄。檢查SELinux是否開(kāi)啟用命令getenforce如果是Enforcing狀態(tài)要么對(duì)數(shù)據(jù)目錄設(shè)置正確的上下文標(biāo)簽要么臨時(shí)關(guān)閉SELinux來(lái)定位問(wèn)題。給目錄打標(biāo)簽的命令是semanage fcontext -a -t mysqld_db_t /data/mysql(/.*)? restorecon -Rv /data/mysql如果你不確定這個(gè)操作是否必須可以先用ls -Z /var/lib/mysql看下原目錄的SELinux標(biāo)簽然后保持一致即可。4.3 第三步停服、拷貝數(shù)據(jù)、改配置確認(rèn)新目錄準(zhǔn)備就緒后開(kāi)始正式遷移。操作順序不能亂停掉MySQL服務(wù)systemctl stop mysqld確認(rèn)服務(wù)已經(jīng)停止沒(méi)有殘留進(jìn)程ps -ef | grep mysqld用rsync拷貝數(shù)據(jù)文件這里我強(qiáng)烈建議用rsync而不是cp。原因有兩點(diǎn)一是rsync支持?jǐn)帱c(diǎn)續(xù)傳數(shù)據(jù)量大的時(shí)候萬(wàn)一中斷不用從頭再來(lái)二是rsync可以很好地保留文件權(quán)限、時(shí)間戳、屬主信息。命令如下rsync -av /var/lib/mysql/ /data/mysql/注意源目錄末尾的斜杠不能省略它表示拷貝目錄內(nèi)的所有內(nèi)容到目標(biāo)目錄而不是把mysql這個(gè)文件夾本身嵌套進(jìn)去。修改配置文件[mysqld] datadir/data/mysql socket/data/mysql/mysql.sock pid-file/data/mysql/mysqld.pid這里我需要特別提一下socket和pid-file。默認(rèn)情況下socket文件和pid文件也會(huì)生成在數(shù)據(jù)目錄里如果你只改了datadir重啟后socke文件路徑變了很多依賴socket連接的程序比如本地命令行連接會(huì)報(bào)錯(cuò)。所以這三個(gè)參數(shù)最好一起改保持一致。當(dāng)然如果你的socket是通過(guò)/tmp/mysql.sock或者/var/run/mysqld/mysqld.sock訪問(wèn)的并且你不想影響現(xiàn)有應(yīng)用的連接那也可以不動(dòng)socket路徑只改datadir。這個(gè)取舍根據(jù)你實(shí)際環(huán)境來(lái)定。啟動(dòng)服務(wù)并驗(yàn)證systemctl start mysqld systemctl status mysqld mysql -uroot -p -e SHOW VARIABLES LIKE datadir;如果啟動(dòng)成功并且查到的datadir已經(jīng)變成/data/mysql恭喜你遷移最核心的步驟就完成了。4.4 新裝環(huán)境如何在初始化階段直接指定數(shù)據(jù)目錄如果你是在新機(jī)器上裝MySQL 8.0其實(shí)在一開(kāi)始就可以把數(shù)據(jù)目錄設(shè)置好這樣后面就不用折騰遷移了。兩種方式方式一在初始化命令里指定參數(shù)。官方tar包安裝的MySQL 8.0初始化命令是mysqld --initialize --datadir/data/mysql --usermysql方式二先把配置文件寫(xiě)好再初始化。編輯/etc/my.cnf把datadir寫(xiě)好然后執(zhí)行mysqld --initialize --usermysqlMySQL會(huì)讀取配置文件里的datadir參數(shù)在指定路徑下完成初始化。這里有個(gè)細(xì)節(jié)初始化完成后會(huì)生成一個(gè)臨時(shí)的root密碼記錄在錯(cuò)誤日志里一般在/var/log/mysqld.log或者你自己指定的日志文件第一次登錄時(shí)要先用這個(gè)臨時(shí)密碼然后立刻修改密碼。grep temporary password /var/log/mysqld.log mysql -uroot -p ALTER USER rootlocalhost IDENTIFIED BY 你的新密碼;還有一個(gè)小知識(shí)MySQL 8.0的--initialize默認(rèn)生成隨機(jī)密碼如果想讓root賬號(hào)初始為空密碼僅限本地測(cè)試環(huán)境可以用--initialize-insecure參數(shù)。但生產(chǎn)環(huán)境千萬(wàn)別這么玩空密碼的數(shù)據(jù)庫(kù)在公網(wǎng)上分分鐘被掃到。4.5 Windows環(huán)境下的目錄修改有什么不同Windows下修改MySQL數(shù)據(jù)目錄核心思路和Linux一樣但有一些Windows特有的坑需要注意。默認(rèn)數(shù)據(jù)目錄在C:\ProgramData\MySQL\MySQL Server 8.0\Data修改步驟如下以管理員身份打開(kāi)命令提示符停止MySQL服務(wù)net stop MySQL80把Data目錄整體拷貝到新位置比如D:\MySQLData\Data。注意這里要完整拷貝包括隱藏文件。打開(kāi)C:\ProgramData\MySQL\MySQL Server 8.0\my.ini修改datadir為D:/MySQLData/Data。注意Windows下配置路徑可以用正斜杠或者雙反斜杠單反斜杠會(huì)被解析成轉(zhuǎn)義字符容易出錯(cuò)。還有個(gè)Windows特有的坑MySQL服務(wù)注冊(cè)時(shí)的啟動(dòng)參數(shù)里可能帶著--datadir這個(gè)優(yōu)先級(jí)高于配置文件。需要用regedit打開(kāi)注冊(cè)表找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MySQL80檢查ImagePath的值如果帶--datadir參數(shù)就刪掉或者改成新路徑。不然你改了my.ini服務(wù)啟動(dòng)時(shí)還是會(huì)用注冊(cè)表里的舊路徑。重啟服務(wù)net start MySQL805. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 服務(wù)啟動(dòng)失敗報(bào)錯(cuò)信息怎么看修改數(shù)據(jù)目錄后最常見(jiàn)的失敗場(chǎng)景就是服務(wù)起不來(lái)錯(cuò)誤日志里出現(xiàn)類似這樣的信息[ERROR] MySQL: Cant find error-message file /usr/share/mysql/errmsg.sys [ERROR] Aborting或者是[ERROR] InnoDB: The data directory /data/mysql doesnt exist or is not writable遇到這類問(wèn)題不要慌先看錯(cuò)誤日志日志路徑一般在/var/log/mysql/mysqld.log或者/var/log/mysqld.log也可以手動(dòng)指定--log-error參數(shù)來(lái)明確日志路徑?;九挪轫樞蚴切履夸浭欠翊嬖跈?quán)限是否正確ll /data看下屬主是不是mysqlSELinux是否攔截getenforce臨時(shí)設(shè)為permissive再啟動(dòng)試試配置文件是否被正確讀取mysqld --print-defaults可以看到當(dāng)前生效的配置磁盤空間是否足夠df -h確認(rèn)5.2 遷移后無(wú)法本地連接socket路徑問(wèn)題還有一次你在遷移后遇到ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock這類報(bào)錯(cuò)。這個(gè)報(bào)錯(cuò)的本質(zhì)是命令行客戶端默認(rèn)通過(guò)socket文件連接本地MySQL而socket文件路徑變了因?yàn)閐atadir變了socket默認(rèn)生成在數(shù)據(jù)目錄下客戶端還是按老路徑去找自然找不到。解決辦法是在/etc/my.cnf的[client]段也寫(xiě)上對(duì)應(yīng)的socket路徑[client] socket/data/mysql/mysql.sock這樣你在命令行執(zhí)行mysql -uroot -p時(shí)客戶端會(huì)自動(dòng)使用配置里的socket路徑連接不會(huì)再去老地方傻找了。5.3 遷移后無(wú)法遠(yuǎn)程連接網(wǎng)絡(luò)層的坑有個(gè)問(wèn)題容易被忽略——改了socket和datadir之后如果恰好你的MySQL沒(méi)有開(kāi)啟網(wǎng)絡(luò)監(jiān)聽(tīng)默認(rèn)情況下bind-address127.0.0.1或者你之前一直通過(guò)socket連接現(xiàn)在換了一臺(tái)機(jī)器想遠(yuǎn)程連數(shù)據(jù)庫(kù)你會(huì)發(fā)現(xiàn)怎么都連不上。這個(gè)時(shí)候可以先確認(rèn)SHOW VARIABLES LIKE bind_address; SHOW VARIABLES LIKE port;如果bind_address是127.0.0.1說(shuō)明MySQL只監(jiān)聽(tīng)本地回環(huán)地址外部機(jī)器自然連不上。需要改成0.0.0.0監(jiān)聽(tīng)所有網(wǎng)卡或者指定內(nèi)網(wǎng)IP同時(shí)注意配置防火墻放行3306端口。這個(gè)和目錄遷移沒(méi)有直接關(guān)系但往往在遷移配置大調(diào)整時(shí)被無(wú)辜牽連進(jìn)來(lái)排查起來(lái)比較迷惑。5.4 常見(jiàn)問(wèn)題速查表我把改目錄過(guò)程中頻率最高的幾類問(wèn)題整理成了一個(gè)速查表方便你遇到問(wèn)題時(shí)快速對(duì)照現(xiàn)象可能原因排查/解決辦法啟動(dòng)報(bào)Permission denied新目錄屬主不是mysqlchown -R mysql:mysql /data/mysql啟動(dòng)報(bào)Cant find error-message file數(shù)據(jù)不完整缺少初始文件確認(rèn)是否做了完整拷貝新裝環(huán)境先初始化啟動(dòng)報(bào)Directory doesnt exist目錄未創(chuàng)建或路徑寫(xiě)錯(cuò)確認(rèn)目錄存在、配置無(wú)拼寫(xiě)錯(cuò)誤本地連接報(bào)Cant connect through socketsocket路徑變了客戶端還用舊路徑在[client]段同步socket路徑服務(wù)啟動(dòng)了但連不上遠(yuǎn)程bind_address只監(jiān)聽(tīng)本地修改bind_address并放行防火墻啟動(dòng)成功但數(shù)據(jù)“丟了”拷貝不完整或目錄搞錯(cuò)停止服務(wù)核對(duì)原目錄文件完整性遷移后部分表?yè)p壞拷貝過(guò)程中服務(wù)未完全停止遷移前務(wù)必systemctl stop mysqld并確認(rèn)無(wú)殘留進(jìn)程5.5 獨(dú)家避坑心得三個(gè)我后來(lái)才悟到的細(xì)節(jié)細(xì)節(jié)一遷移前一定要做備份。這不是廢話我見(jiàn)過(guò)不止一個(gè)人在遷移過(guò)程中因?yàn)檎`操作刪除了原目錄然后新目錄又不完整最后只能靠冷備份恢復(fù)。在任何數(shù)據(jù)目錄操作前至少執(zhí)行一次mysqldump --all-databases把邏輯備份導(dǎo)出或者直接打個(gè)壓縮包放在別的機(jī)器上。數(shù)據(jù)量大的環(huán)境這步該做還得做寧可多花十分鐘備份也不要拿數(shù)據(jù)去賭。細(xì)節(jié)二MySQL 8.0.30之后的redo log結(jié)構(gòu)變化。如果你是從老版本學(xué)來(lái)的遷移經(jīng)驗(yàn)知道要拷貝ib_logfile0和ib_logfile1但新版本里這兩個(gè)文件已經(jīng)不存在了取而代之的是#innodb_redo目錄。拷數(shù)據(jù)時(shí)看到?jīng)]有這些文件不用慌張直接把整個(gè)目錄完整拷過(guò)去就行不要自己動(dòng)里面的文件。細(xì)節(jié)三改完配置后先別急著刪除原目錄。我的習(xí)慣是新目錄啟動(dòng)正常、數(shù)據(jù)驗(yàn)證通過(guò)、業(yè)務(wù)跑了一兩天穩(wěn)定之后再考慮清理原目錄。這樣可以給你留一條隨時(shí)回滾的退路。畢竟生產(chǎn)環(huán)境最怕的就是回不了頭。6. 驗(yàn)證與收尾確保遷移萬(wàn)無(wú)一失數(shù)據(jù)目錄遷移完、服務(wù)也啟動(dòng)成功之后不要急著把原目錄刪了先做一輪完整的功能驗(yàn)證。順序如下登錄MySQL執(zhí)行基礎(chǔ)查詢SELECT * FROM mysql.user LIMIT 5; USE sys; SHOW TABLES;確保系統(tǒng)庫(kù)正常沒(méi)有報(bào)錯(cuò)。找一個(gè)業(yè)務(wù)庫(kù)執(zhí)行一次全表掃描和一次索引查詢對(duì)比遷移前后查詢結(jié)果是否一致。如果有需要可以跑一個(gè)CHECK TABLECHECK TABLE 你的表名;檢查binlog、錯(cuò)誤日志、慢查詢?nèi)罩臼欠裾?xiě)入新目錄。有些環(huán)境把日志目錄也單獨(dú)指定了要確認(rèn)日志文件不是還在老目錄。確認(rèn)數(shù)據(jù)完整性對(duì)比記錄數(shù)mysql -uroot -p -e SELECT table_schema, SUM(table_rows) FROM information_schema.tables GROUP BY table_schema;以上操作都完成后遷移才算真正結(jié)束。最后再啰嗦一句無(wú)論你多熟練任何涉及數(shù)據(jù)目錄的操作都先把備份做了這既是職業(yè)素養(yǎng)也是對(duì)自己和團(tuán)隊(duì)負(fù)責(zé)。