1. 程式人生 > >Mysql新增欄位到大資料表導致鎖表

Mysql新增欄位到大資料表導致鎖表

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">      年初跳完槽,終於可以安心開始寫一些部落格了。進入新的公司,還是有蠻多收穫的。那就先記一個昨天遇到的問題吧。</span>

     昨天晚上7點左右,對一張表進行加欄位,大概200多萬條記錄,欄位90多個的大表,結果造成mysql鎖表,進而導致服務不可用。執行語句如下:

ALTER TABLE `sc_stockout_order` ADD `route_remarks` VARCHAR(1024)  CHARACTER SET utf8mb4  NULL  DEFAULT 
   

     mysql配置如下:


開啟服務期日誌,發現有如下報錯:

Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; 
        nested exception is org.apache.tomcat.jdbc.pool.PoolExhaustedException: 
        [DubboServerHandler-10.162.99.129:20880-thread-105] Timeout: Pool empty. 
        Unable to fetch a connection in 50 seconds, none available[size:80; busy:79; idle:0; lastwait:50000].
        at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:26) ~[mybatis-3.2.8.


我們發現數據庫jdbc拿不到連結,雖然沒有到300最大資料庫連線數,但是兩臺伺服器80*2=160個連結數已經達到配置的客戶端最大連線數。這邊也說明我們客戶端配置的連結數不太合理,可以再稍微調大一點。

        發現這個問題後,為了儘快恢復線上服務,用show processlist發現ALTER TABLE這條語句導致大量查詢語句處於等待狀態,趕緊kill 掉修改表格語句的程序,此時系統恢復正常。在這個當中,發現了一條語句如下:

Waiting for table metadata lock


從圖中也可以看到活躍連線數到160之後就不變了,kill掉程序後恢復。

事後查詢資料:

Mysql在5.6版本之前,直接修改表結構的過程中會鎖表,具體的操作步驟如下:
(1)首先建立新的臨時表,表結構通過命令ALTAR TABLE新定義的結構
(2)然後把原表中資料匯入到臨時表
(3)刪除原表
(4)最後把臨時表重新命名為原來的表名

具體ddl如何工作

參考:http://www.cnblogs.com/cchust/p/4639397.html

Mysql 5.6 雖然引入了Online DDL,但是並不是修改表結構的時候,一定不會導致鎖表,在一些場景下還是會鎖表的,比如
①某個慢SQL或者比較大的結果集的SQL在執行,執行ALTER TABLE時將會導致鎖表發生;
②存在一個事務在操作表的時候,執行ALTER TABLE也會導致修改等待;
檢視我們mysql的版本:SELECT VERSION();  給出:5.6.16-log
我們通過Mysql的慢SQL控制檯,也在發生問題的時間段內沒有出現慢SQL,所以需要排除第一種可能性;
由於當時沒有保留現場,所以當時是不是由於事物導致的鎖表,現在也無從查起,這隻能下次檢視分析了。

根據這次教訓,得到注意項:

1、儘量選擇流量小的事後執行。當天20:00要大促,所以19:00大量供應商在操作。當我們選擇在22:00左右再次執行時,就沒再出現這個問題

2、執行時先看一下有沒有未提交的事務,注意檢視事物information_schema.innodb_trx表

3、隨時關注伺服器日誌狀況,已有問題要先行解決。

4、後續可現在預發環境或測試環境先行模擬,評估風險