1. 程式人生 > 其它 >MySQL 資料庫表無法新增欄位

MySQL 資料庫表無法新增欄位

技術標籤:MySQL資料庫mysqljava

文章目錄


1. 問題描述

有一張MySQL資料庫表,業務變動,需要新增一個業務欄位,於是直接用下面的SQL語句進行欄位新增:

ALTER TABLE table_name ADD `add_field` tinyint(1) DEFAULT NULL COMMENT '新增欄位';

使用Navicat for MySQL執行該語句會報一個錯誤,如下圖所示:
image.png
2013 - Lost connection to MySQL server during query,翻譯過來就是在查詢過程中,MySQL

伺服器失去連線。

該問題是大約一年前遇到的,最近整理筆記看到了,趁有時間做一些整理記錄。但是當時的具體環境已經無法復現了。

2. 官方解釋

檢視MySQL官方對該錯誤的解釋

B.3.2.3 Lost connection to MySQL server
There are three likely causes for this error message.

連線 MySQL 服務丟失,這個錯誤訊息有以下幾個可能的原因。

Usually it indicates network connectivity trouble and you should check the condition of your network if this error occurs frequently. If the error message includes “during query,” this is probably the case you are experiencing.

(1)通常它表示網路連線問題,如果這個錯誤經常發生,你應該檢查你的網路狀況。如果錯誤訊息包括"during query",這可能是您正在經歷的情況。

Sometimes the “during query” form happens when millions of rows are being sent as part of one or more queries. If you know that this is happening, you should try increasing net_read_timeout from its default of 30 seconds to 60 seconds or longer, sufficient for the data transfer to complete.

(2)有時,當數百萬行作為一個或多個查詢的一部分被髮送時,會發生"during query"的錯誤。如果你知道發生了什麼,您應該嘗試將net_read_timeout從預設的30秒增加到60秒或足以完成資料傳輸的更長時間。

More rarely, it can happen when the client is attempting the initial connection to the server. In this case, if your connect_timeout value is set to only a few seconds, you may be able to resolve the problem by increasing it to ten seconds, perhaps more if you have a very long distance or slow connection. You can determine whether you are experiencing this more uncommon cause by using SHOW GLOBAL STATUS LIKE ‘Aborted_connects’. It increases by one for each initial connection attempt that the server aborts. You may see “reading authorization packet” as part of the error message; if so, that also suggests that this is the solution that you need.

(3)更罕見的情況是,當客戶端試圖初始連線到伺服器時,可能會發生這種情況。在這種情況下,如果connect_timeout值設定為只有幾秒,那麼可以通過將其增加到10秒來解決這個問題,如果你的網路距離很長或者網速很慢,則可能需要更長的時間。你可以通過檢視Aborted_connects來確定你是否正在經歷這種更不常見的原因。伺服器每中止一個初始連線嘗試,它的值就會增加1。如果錯誤訊息包括"reading authorization packet",表明這是您所需要的解決方案。

SHOW GLOBAL STATUS LIKE 'Aborted_connects'

If the cause is none of those just described, you may be experiencing a problem with BLOB values that are larger than max_allowed_packet, which can cause this error with some clients. Sometime you may see an ER_NET_PACKET_TOO_LARGE error, and that confirms that you need to increase max_allowed_packet.

(4)如果原因不是以上所述的,你可能遇到了BLOB值大於max_allowed_packet的問題,這可能導致某些客戶端出現此錯誤。有時你可能還會看到一個ER_NET_PACKET_TOO_LARGE錯誤,可以確定是需要提高max_allowed_packet的值了。

SHOW VARIABLES LIKE '%max_allowed_packet%';

3. 解決辦法

綜上所述,不難看出其實比較符合第一條解釋。結合當時那家公司的網路,確實經常的時斷時續的,網路環境比較差。

MySQL 的這個錯誤除了官方說的幾種情況,還需要針對自己的業務場景進行適當探索和甄別,具體情況具體分析。這裡再記錄一下另一種可能,因為ALTER TABLE操作是比較耗時的,所以也很有可能是因為超時原因報的錯誤。查詢關於超時時間的系統變數:

SHOW VARIABLES LIKE '%timeout%';

關於查詢結果中各種超時時間變數的解釋可以參考官方文件中的伺服器系統變數

高效能MySQL這本書的第四章Schema與資料優化提到了以下內容:

MySQL 的 ALTER TABLE 操作的效能對大表來說是個問題。MySQL 執行大部分修改表結構操作的方法是用新的結構建立一個空表,從舊錶中查出所有資料插入新表,然後刪除舊錶。這樣操作可能需要花費很長時間,如果記憶體不足表又很大,而且還有很多索引的情況下尤其如此。

一般而言,大部分 ALTER TABLE 操作將導致 MySQL 服務中斷。對於常見場景,能使用的技巧只有兩種:一種是先在一臺不提供服務的機器上執行 ALTER TABLE 操作,然後和提供服務的主庫進行切換;另一種技巧是影子拷貝,就是用要求的表結構建立一張與源表無關的新表,然後通過重新命名和刪表操作交換兩張表。

ALTER TABLE 允許使用 ALTER COLUMN、MODIFY COLUMN、CHANGE COLUMN三種語句修改列。這三種操作都是不一樣的。

可以結合 MySQL 錯誤日誌,找到需要修改的系統變數,進行相應修改即可。