記一次MySQL資料庫拒絕訪問的解決過程

2022-02-26 19:43:19 字數 3452 閱讀 2004

用wordpress搭部落格,資料庫採用mysql。為了除錯方便,建立賬戶my_account,允許它從任意主機訪問資料庫。

create user `my_account`@'%' identified by 'my_password';
修改 wp-config.php 相應配置,注意db_host設定為127.0.0.1

define('db_user', 'my_account'); // 賬號

define('db_password', 'my_password'); // 密碼

define('db_host', '127.0.0.1'); // 資料服務位址

部署到雲伺服器上,本地瀏覽器訪問部落格,提示資料庫拒絕訪問(本地連線遠端資料沒問題),以下為錯誤日誌。

error 1045 (28000): access denied for user 'my_account'@'localhost' (using password: yes)`
簡單排查後,解決了問題,這裡記錄下解決方案,以及出錯的原因。

1、方案一:刪除 mysql.user表 中,host欄位為 localhost 的匿名賬號(賬戶名為空)。

2、方案二:建立 my_account@localhost 賬戶,用於本地連線資料庫。

筆者採用了方案 一。

首先,確認下 mysql.user 表中是否存在匿名賬戶。

mariadb [(none)]> select user, host from mysql.user where host = 'localhost' and user = '';

+------+-----------+

| user | host |

+------+-----------+

| | localhost |

+------+-----------+

1 row in set (0.00 sec)

接著,刪除相應匿名賬戶,再次嘗試登陸,成功。

mariadb [(none)]> drop user ''@'localhost';

query ok, 0 rows affected (0.00 sec)

為什麼匿名賬戶會導致資料庫連線失敗?

需要對mysql的賬戶建立、客戶端連線校驗有一定的了解。

基礎語法如下:

create user 賬戶名@主機 identified by 密碼;
注意點:(以下用 user 指代賬戶名,host 指代 主機)

host 表示 允許賬戶從哪台主機訪問資料庫。主要用於做安全限制,可以是 主機名、ip位址、%(萬用字元);

user 允許重複,只要 host 是不同的就行。

當 host 設定為 % 時,表示允許從任意主機連線資料庫。

比如,存在兩個xiaoming賬戶,乙個允許從本機連線資料庫,乙個允許從 14.215.177.39 連線資料庫。

mariadb [(none)]> select user, host from mysql.user where user = 'xiaoming';           

+---------+---------------+

| user | host |

+---------+---------------+

| xiaoming | 14.215.177.39 |

| xiaoming | localhost |

+---------+---------------+

2 rows in set (0.00 sec)

也就是 user 為空的賬戶,可以匹配任意使用者名稱。如下指令建立了匿名賬戶。

create user ''@'localhost' identified by 'pwd3';
資料庫伺服器收到客戶端連線,首先會進行身份校驗,將 user、host、password 字段,跟 mysql.user 表裡的記錄進行比較,確認是否合法賬戶。

這裡有個問題:如果 mysql.user表 中存在多條匹配記錄,該以哪條記錄為準?

答案是「優先順序」。大致規則如下:

首先,檢查 host 字段。如果有多個 host 符合條件,則選擇匹配度最高的記錄(ip位址 > 萬用字元%)。

其次,檢查 user 字段。如果有多個 user 符合條件,則選擇匹配度最高的記錄。匿名使用者可以匹配任何使用者,因此匹配度最低。

舉例,假設本地資料庫有如下兩個賬戶(password欄位實際非明文)。

+------------+-----------+-----------+

| user | host | password |

+------------+-----------+-----------+

| my_account | % | 123 |

| | localhost | 456 |

+------------+-----------+-----------+

執行如下命令,最終登入的賬戶,匹配的是 第2條 記錄。(讀者可自行嘗試,輸入密碼123登入失敗,輸入456登入成功)

mysql -u my_account -p
為什麼呢?回顧下匹配的優先順序。

首先,檢查 host 字段。localhost、% 都符合要求。localhost 匹配度高於 %,因此匹配到第2條記錄。

接著,檢查 user 字段。第2條記錄是匿名賬戶,可匹配任意user值,因此,第2條記錄符合要求。

因此,雖然賬戶 my_account 的 host欄位 為%,但是在本地(資料庫所在主機)連線資料庫時,因為上述規則的存在,mysql 會認為你是用匿名賬戶在登入。

my_account 跟匿名賬戶的密碼是不同的,因此密碼校驗不通過,拒絕訪問。

因匿名使用者存在,導致本地連線資料庫拒絕連線,這個問題很常見,有不少人認為這是mysql的設計缺陷,比如 這裡。

了解了mysql的身份驗證邏輯,遇到類似問題也就有思路了。關於%萬用字元,匹配優先順序,上文並沒有詳細展開,感興趣的讀者可以自行檢視官方文件。

另外,mysql拒絕訪問的原因有多種,讀者應具體問題具體分析。

如有錯漏,敬請指出。

host wildcard % which is said in docs that means "all hosts" excludes localhost

6.2.4 access control, stage 1: connection verification

原文首發在筆者的個人部落格,位址在這裡

記一次MySQL資料庫crash事件

mysql8.0資料庫最近一次不知道怎麼回事,突然啟動不了,如下提示 mysql daemon failed to start 日誌如下 網上也找了很多資料,但都處理不了 因為本人安裝資料庫習慣將安裝好的資料庫移到移到其他目錄,所以做了乙個操作,用原來的覆蓋現有的檔案 左邊是原始資料庫檔案,右邊是移...

mysql資料庫翻核 記一次mysql的調優

問題現象 mysql cpu占用188 多核 解決方法 1.跟蹤慢查詢 vi etc my.cnf 在mysqld下增加如下內容 log slow queries slow.log long query time 5 含義為記錄查詢時間超過5秒的sql到slow.log 查詢slow.log的內容,...

記一次mysql資料庫失而復得過程

由於是自己買的vps搭建的部落格,用的是軍哥的一鍵lnmp原始碼編譯安裝的,文章也就幾篇,對備份並不太重視,想著等伺服器快到期的時候備份一下不就行了。後來在該伺服器上測試lnmp分別編譯編譯安裝和使用yum各自安裝,及nginx與php關聯,寫了乙個用yum安裝lnmp的指令碼,想著把該指令碼用sc...