
裝機(jī)這件事尤其是一臺(tái)干干凈凈的服務(wù)器要從零開始部署 MySQL我前后折騰了不下幾十次。從最早官網(wǎng)下個(gè)安裝包一路下一步到后來(lái)在 Linux 上寫腳本靜默安裝再到幫同事排查各種連不上、起不來(lái)的問(wèn)題MySQL 的下載安裝及配置看起來(lái)是入門第一課但恰恰是這一課最容易埋坑。版本選錯(cuò)、初始化密碼丟失、字符集不對(duì)、認(rèn)證插件不兼容任何一個(gè)點(diǎn)都能卡住半天。所以今天把整個(gè)流程從選版本、下載、安裝、初始化配置到故障排查一次性寫透適合剛準(zhǔn)備自己部署數(shù)據(jù)庫(kù)的開發(fā)者也適合那些已經(jīng)“能跑但總覺(jué)得哪里不對(duì)勁”的人。1. 動(dòng)手之前先搞清楚自己和這臺(tái)機(jī)器的真實(shí)需求1.1 先選版本再談安裝很多人第一件事就是打開瀏覽器搜下載鏈接這其實(shí)是最容易后悔的做法。MySQL 的版本選擇直接決定了后面幾年你維護(hù)數(shù)據(jù)庫(kù)時(shí)的心情。目前主流的社區(qū)版本就兩條線5.7 和 8.0。如果這是新項(xiàng)目、新環(huán)境我基本無(wú)腦推薦 8.0。原因很簡(jiǎn)單8.0 默認(rèn)支持 utf8mb4 字符集emoji 和生僻字不用單獨(dú)處理有窗口函數(shù)和公共表表達(dá)式寫統(tǒng)計(jì) SQL 比 5.7 舒服太多默認(rèn)認(rèn)證插件是 caching_sha2_password安全性更高。而且 MySQL 5.7 的官方維護(hù)早已進(jìn)入尾聲很多新硬件和操作系統(tǒng)對(duì)新版本支持更好。但如果你要維護(hù)的是老項(xiàng)目主從架構(gòu)已經(jīng)跑了好幾年客戶端還是老版本的 JDBC 驅(qū)動(dòng)或者老版圖形工具那 5.7 反而更穩(wěn)妥。8.0 默認(rèn)的認(rèn)證插件很多老客戶端不認(rèn)報(bào)錯(cuò)信息直接就是 Authentication plugin caching_sha2_password cannot be loaded升級(jí)驅(qū)動(dòng)若是來(lái)不及項(xiàng)目就只能干瞪眼。另外還有一個(gè)容易忽略的點(diǎn)MySQL 社區(qū)版和企業(yè)版的區(qū)別。企業(yè)版帶備份、監(jiān)控、審計(jì)這些商業(yè)化組件但那都是付費(fèi)的。絕大多數(shù)場(chǎng)景用社區(qū)版就足夠了功能上沒(méi)有閹割性能也一樣不要因?yàn)槊掷飵А吧鐓^(qū)”就覺(jué)得是個(gè)簡(jiǎn)化版。1.2 安裝包的三種獲取渠道和選擇邏輯確定版本之后再考慮從哪里拿安裝包。這里有三種常見(jiàn)渠道側(cè)重點(diǎn)完全不同。第一種是官網(wǎng)的下載頁(yè)。這個(gè)最靠譜版本最全GPL 協(xié)議的社區(qū)版就在里邊。官網(wǎng)會(huì)提供各種平臺(tái)的安裝包Windows 下有 MSI 安裝器和 ZIP 壓縮包兩種形態(tài)Linux 下有 RPM、DEB 包和 tar.gz 源碼包。如果你不確定裝什么就直接選帶“Installer”字樣的 MSI 版它能引導(dǎo)你完成整個(gè)安裝過(guò)程。第二種是公共軟件倉(cāng)庫(kù)或鏡像站點(diǎn)。這類渠道的優(yōu)勢(shì)是速度快尤其是部分網(wǎng)絡(luò)環(huán)境訪問(wèn)官網(wǎng)不穩(wěn)定的時(shí)候從鏡像拉取能省不少時(shí)間。但要注意鏡像站上的版本可能不是最新的偶爾還會(huì)出現(xiàn)同步延遲。下載完多一步校驗(yàn)工作核對(duì)一下安裝包的哈希值這一步不難但很值得做防止拿到損壞或不完整的文件。第三種是內(nèi)網(wǎng)軟件源或本地自建倉(cāng)庫(kù)。公司或團(tuán)隊(duì)內(nèi)部如果已經(jīng)維護(hù)了自己的軟件源直接從里面拉取是最規(guī)范的做法版本統(tǒng)一、依賴可控還能在離線環(huán)境下安裝。我見(jiàn)過(guò)很多內(nèi)網(wǎng)環(huán)境完全不能訪問(wèn)外部網(wǎng)絡(luò)這時(shí)候內(nèi)網(wǎng)鏡像和離線 RPM 包就是救命稻草。1.3 環(huán)境準(zhǔn)備一臺(tái)干凈的機(jī)器比什么都重要很多人忽略了裝前的環(huán)境檢查直接開裝然后被各種莫名其妙的錯(cuò)誤打斷。其實(shí)檢查就三件事。磁盤和內(nèi)存是否夠用。MySQL 8.0 安裝完基礎(chǔ)占用大概 1GB 左右數(shù)據(jù)目錄還要預(yù)留空間。內(nèi)存方面開發(fā)環(huán)境 2GB 勉強(qiáng)能跑生產(chǎn)環(huán)境建議至少 4GB并且要提前規(guī)劃 InnoDB 緩沖池的大小。端口 3306 是否空閑也很關(guān)鍵尤其 Windows 上裝過(guò)其他數(shù)據(jù)庫(kù)軟件或者被別的進(jìn)程占了端口安裝時(shí)配置那一關(guān)就會(huì)卡住。操作系統(tǒng)的基礎(chǔ)組件是否齊全。Windows 環(huán)境下MySQL 安裝器依賴微軟的 VC 運(yùn)行庫(kù)缺了它會(huì)在檢測(cè)環(huán)境那一步失敗。Linux 環(huán)境下RPM 安裝時(shí)經(jīng)常提示缺少依賴比較常見(jiàn)的是 libaio、numactl 之類的庫(kù)需要提前裝上。虛擬機(jī)場(chǎng)景下先打個(gè)快照。這一步真的是無(wú)數(shù)血淚換來(lái)的經(jīng)驗(yàn)安裝配置過(guò)程中如果搞亂了系統(tǒng)配置回滾快照比反安裝干凈一百倍。我就是有一次在測(cè)試機(jī)里反復(fù)卸載重裝最后 MySQL 服務(wù)殘留了一大堆費(fèi)了半天勁才清理干凈。2. Windows 上把 MySQL 裝起來(lái)并且當(dāng)場(chǎng)驗(yàn)證2.1 安裝類型怎么選全量、只裝服務(wù)端還是自定義Windows 下用 MSI 安裝器是最省心的方式。雙擊打開后會(huì)有幾個(gè)安裝類型選項(xiàng)很多人直接選默認(rèn)的 Developer Default結(jié)果裝了一堆用不上的組件。Developer Default 會(huì)安裝 MySQL 服務(wù)端、MySQL Shell、Router、各種語(yǔ)言的連接器、文檔、示例數(shù)據(jù)庫(kù)甚至還有 Excel 插件。如果是給一個(gè)專門的數(shù)據(jù)庫(kù)服務(wù)器用這些東西基本都是多余的白占磁盤空間還拖慢安裝速度。Server only 是最精簡(jiǎn)的只裝服務(wù)端和客戶端命令行工具適合純粹要跑數(shù)據(jù)庫(kù)的場(chǎng)景。Custom 是自定義適合像我這種喜歡掌控每個(gè)目錄位置的人。我的建議是本機(jī)開發(fā)用 Developer Default 沒(méi)什么問(wèn)題圖省事。但如果是部署服務(wù)器選 Server only需要的工具用的時(shí)候再單獨(dú)裝保持環(huán)境干凈。另外一個(gè)選擇是 ZIP 免安裝包。這個(gè)方式其實(shí)很適合批量部署解壓之后改一下配置文件執(zhí)行初始化命令注冊(cè)成 Windows 服務(wù)就能用。不用走圖形安裝器的向?qū)窂胶托袨槎伎煽亍2贿^(guò)它需要手寫配置文件和手工初始化對(duì)新手來(lái)說(shuō)門檻稍微高一點(diǎn)。2.2 配置實(shí)例時(shí)容易被忽略的幾項(xiàng)選擇安裝類型之后就到了配置實(shí)例這一步這里面的細(xì)節(jié)直接影響后續(xù)使用。第一個(gè)是 Config Type。這個(gè)選項(xiàng)會(huì)出現(xiàn)三個(gè)類型Development Machine、Server Machine、Dedicated Machine。它們的區(qū)別不是安裝位置而是 MySQL 會(huì)根據(jù)類型自動(dòng)估算內(nèi)存占用、連接數(shù)和 InnoDB 緩沖池大小。本地開發(fā)機(jī)選 Development 就行會(huì)留更多內(nèi)存給其他應(yīng)用專用數(shù)據(jù)庫(kù)服務(wù)器選 Server 或 DedicatedMySQL 會(huì)吃下更多內(nèi)存以換取性能。我之前在測(cè)試機(jī)上選了 Dedicated Machine結(jié)果數(shù)據(jù)庫(kù)把內(nèi)存占滿了開發(fā)工具全部卡頓后來(lái)才反應(yīng)過(guò)來(lái)是這個(gè)配置的原因。第二個(gè)是端口和網(wǎng)絡(luò)。默認(rèn) 3306 基本不用改但要注意 TCP/IP 勾選之后的地址范圍。默認(rèn)情況下 MySQL 監(jiān)聽(tīng)所有網(wǎng)絡(luò)接口如果只有本機(jī)訪問(wèn)其實(shí)可以配置成只監(jiān)聽(tīng) 127.0.0.1減少暴露風(fēng)險(xiǎn)。生產(chǎn)上需要遠(yuǎn)程連接時(shí)再放開到指定 IP而不是粗暴地監(jiān)聽(tīng)所有地址。第三個(gè)是認(rèn)證方式。8.0 安裝的時(shí)候會(huì)問(wèn)你要不要用舊版認(rèn)證默認(rèn)是新的 caching_sha2_password。需要特別注意這一點(diǎn)如果公司的老項(xiàng)目用的是老版本 JDBC 驅(qū)動(dòng)、老版 Navicat 或者其他跟不上時(shí)代的客戶端建議直接勾選兼容選項(xiàng)。否則裝完之后本地命令行能連遠(yuǎn)程或者程序連就報(bào)錯(cuò)。第四個(gè)是密碼。安裝過(guò)程會(huì)要求設(shè)置 root 密碼這里的難點(diǎn)在于 MySQL 8.0 默認(rèn)密碼策略比較嚴(yán)格要求至少 8 位且包含大小寫、數(shù)字和特殊字符。你可以后續(xù)再調(diào)整策略但初始設(shè)置時(shí)最好記到自己的密碼管理工具里。密碼忘了的恢復(fù)過(guò)程雖然可行但比較折騰后面會(huì)詳細(xì)講。2.3 完成安裝后的第一次連接測(cè)試安裝完成后先別急著關(guān)窗口當(dāng)場(chǎng)做一次連接測(cè)試確認(rèn)服務(wù)真的能工作。打開命令行用 mysql -u root -p 登錄輸入剛才設(shè)置的密碼。如果出現(xiàn) mysql 不是內(nèi)部或外部命令 的報(bào)錯(cuò)說(shuō)明 MySQL 的 bin 目錄沒(méi)有加到 PATH 環(huán)境變量里。MSI 安裝器一般會(huì)自動(dòng)配置但如果沒(méi)生效手動(dòng)把安裝目錄下的 bin 路徑加進(jìn)去就行。登錄成功之后執(zhí)行幾條基礎(chǔ)命令驗(yàn)證狀態(tài)SELECT VERSION(); SHOW DATABASES;第一條能看到當(dāng)前版本號(hào)第二條能看到初始化好的幾個(gè)默認(rèn)數(shù)據(jù)庫(kù)。到這里 MySQL 服務(wù)端基本就算是正常工作了。接下來(lái)我還會(huì)順手執(zhí)行一條 SHOW VARIABLES LIKE character_set%;看一下字符集配置情況。如果 character_set_server 還是默認(rèn)的 latin1后面就需要在配置文件里改成 utf8mb4這個(gè)在第 4 部分會(huì)細(xì)說(shuō)。3. Linux 服務(wù)器上的靜默安裝與自動(dòng)化腳本3.1 倉(cāng)庫(kù)安裝與 RPM 離線安裝取舍Linux 上部署 MySQL 通常有兩種主流套路一種是通過(guò)官方軟件倉(cāng)庫(kù)在線安裝另一種是下載 RPM 包離線安裝。我兩種都用了很多年各自的優(yōu)劣很清楚。官方軟件倉(cāng)庫(kù)的優(yōu)勢(shì)是省心一條指令就能完成安裝并自動(dòng)處理依賴關(guān)系。在 Red Hat 系的發(fā)行版上需要先安裝官方倉(cāng)庫(kù)的 RPM 配置包然后直接拿 yum 或 dnf 裝 mysql-server。Debian 系則可以配置官方 APT 源之后用 apt 安裝。這種方式適合網(wǎng)絡(luò)暢通、可以訪問(wèn)外部軟件源的環(huán)境。離線 RPM 包則是把 mysql-community-server、mysql-community-client 等一整套包下載下來(lái)在目標(biāo)機(jī)器上手動(dòng)安裝。安裝順序是有講究的一般是 common、libs、client、server 這個(gè)順序因?yàn)楹筮叺陌蕾嚽斑叺膬?nèi)容。用 rmp -ivh 依次安裝如果缺少依賴庫(kù)會(huì)有明確的提示再單獨(dú)補(bǔ)齊就行。這里特別提醒一下不要用系統(tǒng)自帶的默認(rèn)倉(cāng)庫(kù)直接裝 MySQL很多發(fā)行版的軟件源里默認(rèn)的“mysql-server”其實(shí)是 MariaDB 或者某個(gè)舊版本分支。不是說(shuō) MariaDB 不好而是如果你就是沖 MySQL 去的裝出來(lái)一個(gè)跑了 MariaDB 的庫(kù)后面很多參數(shù)和行為都不對(duì)勁。我剛?cè)腴T時(shí)就在這上面吃過(guò)虧折騰半天才搞明白數(shù)據(jù)庫(kù)的內(nèi)核都不一樣。3.2 初始化、目錄權(quán)限和啟動(dòng)服務(wù)RPM 安裝完成之后MySQL 不會(huì)自動(dòng)初始化數(shù)據(jù)目錄。需要執(zhí)行 mysqld --initialize --usermysql 命令注意必須以 mysql 用戶身份執(zhí)行不能直接用 root 跑這也是很多新手會(huì)掉的坑。初始化過(guò)程會(huì)在錯(cuò)誤日志文件里生成一個(gè)臨時(shí) root 密碼。日志文件的位置一般在 /var/log/mysqld.log 或 /var/lib/mysql 目錄下具體看發(fā)行版。第一次啟動(dòng)服務(wù)時(shí)用 grep 過(guò)濾日志里的 temporary password 字樣就能找到。看到密碼之后啟動(dòng)服務(wù)systemctl start mysqld systemctl enable mysqld然后登錄第一件事就是修改初始密碼。因?yàn)槌跏济艽a是一串隨機(jī)字符不修改的話根本沒(méi)法用。mysql -u root -p ALTER USER rootlocalhost IDENTIFIED BY YourStrongPassword;這里還要注意目錄權(quán)限問(wèn)題。如果不小心用 root 初始化過(guò)數(shù)據(jù)目錄之后 MySQL 啟動(dòng)會(huì)報(bào)權(quán)限錯(cuò)誤。徹底的辦法是停掉服務(wù)把 /var/lib/mysql 目錄的屬主改成 mysql 用戶再重新初始化。啟動(dòng)成功后日常巡檢可以只用一條命令mysqladmin -u root -p status這條命令能快速查看 MySQL 的存活狀態(tài)、運(yùn)行時(shí)長(zhǎng)、連接數(shù)和慢查詢計(jì)數(shù)比登錄進(jìn)去敲 SQL 快得多。3.3 一條命令搞定常規(guī)巡檢說(shuō)到巡檢我順手整理幾條平時(shí)用得最頻繁的命令。除了 mysqladmin status還有這幾條查看當(dāng)前所有數(shù)據(jù)庫(kù)連接數(shù)確認(rèn)有沒(méi)有連接堆積SHOW PROCESSLIST;查看 InnoDB 緩沖池實(shí)際命中情況SHOW STATUS LIKE Innodb_buffer_pool_read%;查看慢查詢相關(guān)的配置和狀態(tài)確認(rèn)慢查詢?nèi)罩居袥](méi)有生效SHOW VARIABLES LIKE slow_query_log; SHOW VARIABLES LIKE long_query_time;這些命令組合起來(lái)基本就是數(shù)據(jù)庫(kù)健康體檢的標(biāo)配。不用裝額外的監(jiān)控工具命令行就能把 80% 的問(wèn)題排查掉。4. 初始化配置每個(gè)參數(shù)背后都有代價(jià)4.1 字符集與排序規(guī)則不是小事數(shù)據(jù)庫(kù)能跑起來(lái)之后第一個(gè)要改的就是字符集。MySQL 安裝后默認(rèn)字符集很可能是 latin1這就意味著你存中文勉強(qiáng)能存存 emoji 或者各種特殊符號(hào)就會(huì)報(bào)錯(cuò)或者變成亂碼。MySQL 8.0 的默認(rèn)字符集其實(shí)已經(jīng)改成了 utf8mb4但 5.7 和更早版本不是。而且即便是 8.0也建議確認(rèn)一下實(shí)際生效的配置。最穩(wěn)妥的做法是在配置文件里顯式聲明character-set-serverutf8mb4 collation-serverutf8mb4_0900_ai_ci在 5.7 里排序規(guī)則一般建議 utf8mb4_unicode_ci。utf8mb4 和 utf8 的區(qū)別在于MySQL 里的 utf8 實(shí)際是 utf8mb3最多只能存 3 個(gè)字節(jié)的字符表情符號(hào)根本存不進(jìn)去。所以凡是涉及字符集的配置統(tǒng)一用 utf8mb4 是絕對(duì)沒(méi)錯(cuò)的。另一個(gè)容易忽略的點(diǎn)是連接層的字符集。就算服務(wù)端設(shè)了 utf8mb4客戶端連接時(shí)如果沒(méi)有指定依然會(huì)出現(xiàn)亂碼。在 Linux 命令行登錄時(shí)可以加參數(shù)mysql --default-character-setutf8mb4 -u root -p在 JDBC 連接串里則要加上 characterEncodingutf8mb4 和 useUnicodetrue。這些都是實(shí)際項(xiàng)目中常見(jiàn)的坑。排序規(guī)則的選擇也有講究。utf8mb4_0900_ai_ci 是 8.0 默認(rèn)的ai 表示不區(qū)分重音ci 表示不區(qū)分大小寫。如果業(yè)務(wù)對(duì)大小寫敏感就要改成 utf8mb4_bin 或者 _cs 結(jié)尾的規(guī)則。這屬于業(yè)務(wù)層決策沒(méi)有絕對(duì)的好壞。4.2 賬號(hào)管理與密碼策略root 賬號(hào)只適合本地 DBA 管理用任何業(yè)務(wù)程序都不應(yīng)該用 root 去連庫(kù)。這是我反復(fù)強(qiáng)調(diào)的一點(diǎn)因?yàn)闃I(yè)務(wù)程序中如果數(shù)據(jù)庫(kù)密碼泄露root 權(quán)限意味著整個(gè)數(shù)據(jù)庫(kù)被接管。實(shí)踐上建議單獨(dú)創(chuàng)建業(yè)務(wù)賬號(hào)CREATE USER app_userlocalhost IDENTIFIED BY StrongPssw0rd; GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO app_userlocalhost; FLUSH PRIVILEGES;這里的 host 部分非常關(guān)鍵。localhost 表示只允許本機(jī)連接如果要允許遠(yuǎn)程訪問(wèn)就得換成具體 IP 或者 %。% 表示任意地址能用具體 IP 的時(shí)候盡量不要用 %。密碼策略方面MySQL 8.0 默認(rèn)啟用了 validate_password 組件密碼必須滿足一定復(fù)雜度。這個(gè)組件在安裝時(shí)就生效修改密碼時(shí)如果太簡(jiǎn)單會(huì)被拒絕??梢酝ㄟ^(guò)配置調(diào)整策略等級(jí)SET GLOBAL validate_password.policy LOW;低策略只要求長(zhǎng)度但生產(chǎn)環(huán)境一般不建議降級(jí)。權(quán)限授予遵循最小化原則只給業(yè)務(wù)實(shí)際需要的權(quán)限。需要聯(lián)表查詢就加 SELECT 權(quán)限需要批量寫入就加 INSERT沒(méi)必要一股腦給 ALL PRIVILEGES。權(quán)限給多了出問(wèn)題的時(shí)候排查范圍也大。4.3 慢查詢和日志到底要不要開慢查詢?nèi)罩臼悄壳靶詢r(jià)比最高的性能排查工具我一般建議長(zhǎng)期開啟只是閾值和輸出方式可以按環(huán)境調(diào)整。slow_query_logON long_query_time1 slow_query_log_file/var/log/mysql/slow.loglong_query_time1 表示超過(guò) 1 秒的 SQL 都會(huì)被記錄。對(duì)于線上環(huán)境如果業(yè)務(wù)本來(lái)就復(fù)雜可以適當(dāng)放寬到 2 秒或 3 秒避免日志增長(zhǎng)太快。開發(fā)環(huán)境建議 0.5 秒甚至 0 秒把所有 SQL 都記錄下來(lái)方便性能調(diào)優(yōu)。開啟慢查詢?nèi)罩局蠖ㄆ诳匆槐槿罩灸男?SQL 占用了大量時(shí)間一目了然。配合 EXPLAIN 分析執(zhí)行計(jì)劃基本能定位 90% 的性能問(wèn)題。通用日志 general_log 默認(rèn)是關(guān)閉的它記錄所有執(zhí)行的 SQL信息量太大只有排查特定問(wèn)題時(shí)才建議臨時(shí)打開。還有一個(gè)容易被忽略的日志是二進(jìn)制日志 binlog。如果是單機(jī)使用且不需要數(shù)據(jù)恢復(fù)其實(shí)可以不開啟因?yàn)?binlog 會(huì)占用磁盤空間。但只要是搭建主從復(fù)制binlog 就必須開啟。我見(jiàn)過(guò)一臺(tái)服務(wù)器上 binlog 增長(zhǎng)到幾十 GB 導(dǎo)致磁盤被寫滿的故障排查下來(lái)就是 binlog 過(guò)期時(shí)間沒(méi)有配置。5.7 里用 expire_logs_days8.0 則改成了 binlog_expire_logs_seconds默認(rèn)是 2592000 秒也就是 30 天。如果不小心把保留時(shí)間設(shè)成了 0binlog 就永遠(yuǎn)不會(huì)自動(dòng)清理磁盤遲早被寫爆。4.4 遠(yuǎn)程訪問(wèn)與安全焦慮的平衡“為什么我的 MySQL 遠(yuǎn)程連接不上”是我被問(wèn)過(guò)最多的問(wèn)題。遠(yuǎn)程訪問(wèn)這件事一通百通報(bào)錯(cuò)就那么幾種原因。首先要確認(rèn) MySQL 是否監(jiān)聽(tīng)了所有網(wǎng)卡。配置文件里的 bind-address 如果默認(rèn)是 127.0.0.1那就只監(jiān)聽(tīng)本機(jī)回環(huán)地址局域網(wǎng)其他機(jī)器根本碰不到。改成 0.0.0.0 或者指定業(yè)務(wù)網(wǎng)段的 IP才能從外部連接。其次要確認(rèn)賬號(hào)的 host 設(shè)置。前面講過(guò)app_userlocalhost 只允許本機(jī)登錄需要遠(yuǎn)程連接就要用 app_user192.168.1.% 這種形式。最后是防火墻。Linux 上如果啟用了 firewalld 或者系統(tǒng)防火墻即使 MySQL 配置全對(duì)外部訪問(wèn)依然會(huì)被攔截。開發(fā)環(huán)境圖省事可以直接關(guān)掉防火墻但生產(chǎn)環(huán)境請(qǐng)務(wù)必只放行必要端口并且限定來(lái)源 IP。IPv6 的問(wèn)題偶爾也會(huì)出現(xiàn)。有些環(huán)境里 MySQL 監(jiān)聽(tīng)的是 ::1 而不是 0.0.0.0配置 bind-address 時(shí)要確認(rèn)寫成 * 或者明確指定 0.0.0.0。還有一個(gè)安全方面的細(xì)節(jié)遠(yuǎn)程訪問(wèn)盡量使用獨(dú)立賬號(hào)不要放行 root 的遠(yuǎn)程登錄。root 只保留本機(jī)訪問(wèn)即可。5. 故障排查我替你踩過(guò)的幾個(gè)坑5.1 忘記 root 密碼的三種恢復(fù)思路不管是在本地開發(fā)還是在生產(chǎn)服務(wù)器忘記 root 密碼都是遲早會(huì)遇到的事情?;謴?fù)方式根據(jù)環(huán)境和場(chǎng)景至少有三種選擇。最簡(jiǎn)單的方式是走 skip-grant-tables 模式。這個(gè)模式的原理是 MySQL 啟動(dòng)時(shí)不加載授權(quán)表跳過(guò)所有權(quán)限校驗(yàn)。操作步驟是先停掉正常服務(wù)然后用跳過(guò)授權(quán)表的方式手動(dòng)啟動(dòng)。systemctl stop mysqld mysqld_safe --skip-grant-tables --skip-networking 注意 --skip-networking 一定要加這個(gè)參數(shù)會(huì)禁用遠(yuǎn)程連接避免在無(wú)認(rèn)證狀態(tài)下被網(wǎng)絡(luò)請(qǐng)求攻擊。啟動(dòng)成功后再用 mysql -u root 無(wú)密碼登錄重置密碼FLUSH PRIVILEGES; ALTER USER rootlocalhost IDENTIFIED BY NewStrongPassword;改完密碼后重啟服務(wù)恢復(fù)正常模式。第二種思路是使用 init-file。在配置文件里指定一個(gè)包含重置密碼 SQL 的文本文件啟動(dòng)時(shí) MySQL 會(huì)先執(zhí)行里面的語(yǔ)句。這種方式的好處是服務(wù)正常啟動(dòng)不用經(jīng)歷無(wú)認(rèn)證階段比較適合有嚴(yán)格安全要求的場(chǎng)景。第三種思路是備份和恢復(fù)。如果日常有備份數(shù)據(jù)庫(kù)的邏輯可以直接用最近的備份恢復(fù)這個(gè)代價(jià)最大只作為最后手段。這里要特別說(shuō)一句MySQL 8.0 中 authentication_string 字段存的是密碼哈希不是明文也不支持直接用 update 語(yǔ)句寫簡(jiǎn)單字符串。有人自作聰明執(zhí)行 update mysql.user set authentication_stringpassword where userroot結(jié)果密碼還是不對(duì)。正確做法就是用 ALTER USER 語(yǔ)句讓 MySQL 自己計(jì)算哈希。5.2 遠(yuǎn)程連接報(bào)錯(cuò)的排查路徑遇到客戶端連不上遠(yuǎn)程 MySQL我通常按照一條固定路徑排查從外到內(nèi)一層層剝。先確認(rèn)網(wǎng)絡(luò)通不通。在客戶端機(jī)器上執(zhí)行 ping 和 telnet檢查目標(biāo) IP 的 3306 端口是否能訪問(wèn)。如果 telnet 報(bào)錯(cuò)說(shuō)明問(wèn)題在網(wǎng)絡(luò)層或防火墻數(shù)據(jù)庫(kù)本身即使配置正確也白搭。然后確認(rèn) MySQL 監(jiān)聽(tīng)狀態(tài)。在服務(wù)器上執(zhí)行netstat -tlnp | grep 3306如果結(jié)果只顯示 127.0.0.1:3306說(shuō)明只監(jiān)聽(tīng)了本機(jī)需要修改 bind-address。如果顯示 0.0.0.0:3306 或者具體 IP說(shuō)明監(jiān)聽(tīng)沒(méi)問(wèn)題。最后確認(rèn)賬號(hào)授權(quán)。用 root 本地登錄后查看 hosts 權(quán)限SELECT user, host FROM mysql.user;如果賬號(hào)的 host 是 localhost遠(yuǎn)程就是連不通的。創(chuàng)建一個(gè)允許遠(yuǎn)程的賬號(hào)或者把 host 改為具體網(wǎng)段。然后再試一次連接。很多報(bào)錯(cuò)都是表面現(xiàn)象Cant connect to MySQL server on x.x.x.x (10061) 是端口不通Access denied for user rootx.x.x.x 是權(quán)限問(wèn)題Authentication plugin cannot be loaded 是認(rèn)證插件不兼容。報(bào)錯(cuò)信息不同本質(zhì)原因完全不同不要看到一個(gè)報(bào)錯(cuò)就去改數(shù)據(jù)庫(kù)配置。5.3 性能異常與配置復(fù)核清單MySQL 裝好后正常跑了一段時(shí)間突然變慢了這類問(wèn)題我也遇過(guò)不少。排查時(shí)先別急著調(diào)大各種參數(shù)先看系統(tǒng)層面的狀態(tài)。用 SHOW PROCESSLIST 看看有沒(méi)有大量堆積的連接。這個(gè)輸出能直接看到每個(gè)連接在做什么是正在執(zhí)行慢 SQL還是處于 sleep 狀態(tài)空占連接。如果 sleep 連接特別多說(shuō)明連接池配置有問(wèn)題或者 wait_timeout 設(shè)置得太長(zhǎng)連接沒(méi)有被及時(shí)回收。連接數(shù)被打滿時(shí)會(huì)出現(xiàn) Too many connections 的錯(cuò)誤。這個(gè)錯(cuò)誤的直接原因是 max_connections 不夠用但根因往往不是這個(gè)。應(yīng)用程序的連接池沒(méi)有復(fù)用連接而是一次請(qǐng)求新建一個(gè)連接是最常見(jiàn)的場(chǎng)景。這個(gè)時(shí)候把 max_connections 從 200 調(diào)到 2000 只能治標(biāo)真正該做的是修連接池配置。磁盤 I/O 也是一個(gè)容易被忽略的瓶頸。數(shù)據(jù)庫(kù)所在磁盤如果滿了或者磁盤 I/O 本來(lái)就很差MySQL 的表現(xiàn)就是越來(lái)越慢。用 iostat 或系統(tǒng)自帶監(jiān)控工具看一眼負(fù)載如果 I/O 長(zhǎng)時(shí)間在 90% 以上優(yōu)先考慮優(yōu)化 SQL而不是加內(nèi)存調(diào)參。最后檢查一下 InnoDB 緩沖池大小。innodb_buffer_pool_size 默認(rèn)值在安裝時(shí)不一定適合當(dāng)前業(yè)務(wù)量。當(dāng)前內(nèi)存總量 70% 左右是一個(gè)常見(jiàn)經(jīng)驗(yàn)值但也不是越大越好畢竟系統(tǒng)本身和其他進(jìn)程也要內(nèi)存。5.4 一份可以直接抄的避坑速查表最后整理一份速查表把前面提到的典型問(wèn)題和排查思路集中放進(jìn)來(lái)我平時(shí)排查問(wèn)題時(shí)也會(huì)參考這個(gè)思路?,F(xiàn)象常見(jiàn)原因排查與解決安裝時(shí)卡在 Start Service端口被占用、權(quán)限不足、殘留服務(wù)沖突檢查 3306 端口占用確認(rèn)以管理員身份運(yùn)行安裝器卸載時(shí)清理注冊(cè)表和服務(wù)殘留mysql 命令找不到bin 目錄未加入 PATH把 MySQL 安裝目錄下的 bin 路徑加入系統(tǒng) PATHLinux 啟動(dòng)失敗數(shù)據(jù)目錄權(quán)限錯(cuò)誤、依賴庫(kù)缺失檢查 /var/lib/mysql 屬主是否為 mysql補(bǔ)齊 libaio、numactl 等依賴忘記 root 密碼無(wú)skip-grant-tables 模式重置注意禁用網(wǎng)絡(luò)遠(yuǎn)程連不上監(jiān)聽(tīng)地址、防火墻、賬號(hào) host、認(rèn)證插件按網(wǎng)絡(luò)通斷、監(jiān)聽(tīng)狀態(tài)、賬號(hào)權(quán)限、認(rèn)證插件順序逐層排查中文亂碼或 emoji 報(bào)錯(cuò)字符集不是 utf8mb4統(tǒng)一服務(wù)端、連接層、表字符集為 utf8mb4磁盤被 binlog 占滿binlog 保留時(shí)間未設(shè)置檢查 binlog_expire_logs_seconds及時(shí)清理連接數(shù)被打滿連接池未復(fù)用連接檢查應(yīng)用連接池配置然后考慮調(diào)大 max_connections老客戶端連不上 8.0認(rèn)證插件為 caching_sha2_password升級(jí)客戶端驅(qū)動(dòng)或?qū)①~號(hào)認(rèn)證方式改為 mysql_native_password這個(gè)表其實(shí)覆蓋了我這些年遇到的絕大多數(shù) MySQL 安裝配置問(wèn)題。很多問(wèn)題在官方文檔里都有詳細(xì)說(shuō)明但文本形式的信息密度高。真正上手操作的時(shí)候手邊有一份這樣的清單比翻文檔快得多。聊到這兒我再分享一個(gè)自己一直堅(jiān)持的習(xí)慣每次在一個(gè)新環(huán)境里部署完 MySQL我會(huì)立刻把配置文件、初始化命令、遇到的坑和解決方式記到項(xiàng)目筆記里。不是給自己增加工作量而是半年后再維護(hù)這套環(huán)境的時(shí)候這份筆記就是最省時(shí)間的資料。MySQL 安裝配置看似基礎(chǔ)但恰恰是基礎(chǔ)環(huán)節(jié)最容易因?yàn)椤胺凑瓦@么幾步”而留下隱患。先用對(duì)版本再做對(duì)配置最后留好排查思路這一套流程走下來(lái)數(shù)據(jù)庫(kù)才能真正穩(wěn)定地跑起來(lái)。