曲演雜壇--使用ALTER TABLE修改字段類型的吐血教訓

--=====================================================================數據庫

事件原由:開發發現有表插入數據失敗,查看後發現INT類型自增值已經到了最大值,沒法繼續插入,須要修改INT類型爲BIGINT類型。併發

--=====================================================================工具

做爲一羣自認爲還算有點經驗的老DBA,你們相互商量下,決定刪除複製,而後禁止訪問,刪除索引,再使用ALTER TABLE修改,最後再加回索引,再修改訪問,再不初始化訂閱,多完美的步驟。測試

因而在一羣人嘻哈圍觀中,執行了上述步驟,運行修改腳本:spa

ALTER TABLE TableName
ALTER COLUMN ID BIGINT

而後你們開始預估執行時間,有預估十幾分鐘的,有預估半小時的,有預估兩小時的,而後開始坐等。。。線程

半小時過去,沒有完成,有人開始坐不住,一個小時過去,沒有完成,你們開始着急,兩個小時過去,仍是沒有完成,老闆坐不住啦,殺過來質問。。。3d

這下玩大啦。。。日誌

--=====================================================================code

因爲在多臺機器上執行,一些取消執行,一些硬抗等着執行成功,不管是取消執行仍是繼續執行,都不知道啥時能回滾成功或者執行成功,你們一邊在惶恐中祈禱早點執行完成,一邊還得給老大們解釋各類緣由。blog

--=====================================================================

錶行數:11億+

表數據:60GB+

表狀況:1個BIGINT列+3個INT列+1個VARCHAR(50)列(VARCHAR(50)列平均每行長度11Byte)

修改操做:將字段類型INT改成BIGINT

對於繼續執行等待ALTER TABLE成功的:耗時9.5小時完成

對於執行四小時而後取消執行的:耗時超過10小時未完成

--=====================================================================

扯了這麼多水貨,我們來點乾貨,爲何修改字段類型消耗這麼長時間呢?

首先排查是否由硬件資源瓶頸致使,硬件配置爲:

CPU: 48CORE

內存:128GB

IO: FIO卡或高級共享存儲

CPU使用未超過10%,磁盤每秒日誌寫入8MB左右,內存未發現等待分配狀況

那問題出在那呢?

問題仍是出在日誌上,能夠輕鬆發現,不管是在FIO卡仍是共享存儲上,磁盤每秒日誌寫入8MB左右,這個數值過低,通過肖磊諮詢MS工程師瞭解到,修改數據類型,須要修改每一行的數據,每行數據生成一條日誌記錄,從而致使大量的日誌,而因爲未知緣由,每秒寫入磁盤的日誌量較低,所以致使整個修改操做維持很長時間。

讓咱們來作個測試:

--=======================
--使用測試數據庫DB2
use db2
GO
--================
--建立測試表
CREATE TABLE Test001
(
    C1 INT IDENTITY(1,1),
    C2 BIGINT
)
GO
--================
--往測試表中導入2000+行數據
INSERT INTO Test001(C2)
SELECT OBJECT_ID FROM sys.all_objects
GO
--================
--備份日誌以截斷日誌
BACKUP LOG [db2] TO DISK='NUL'
GO
--================
--查看當前日誌狀況
--因爲日誌截斷,當前日誌記錄數不多
SELECT * FROM sys.fn_dblog(NULL,NULL)
ORDER BY [Current LSN] DESC

GO
--=====================
--修改字段類型
ALTER TABLE Test001
ALTER COLUMN C1 BIGINT
GO
--================
--再次查看當前日誌狀況
--發現增長4000+的日誌記錄數
SELECT * FROM sys.fn_dblog(NULL,NULL)
ORDER BY [Current LSN] DESC


因爲咱們操做的數據有11億+條,整個ALTER TABLE 操做是一個完整的事務操做,所以是一個極其龐大的事務,再加上其餘諸如複製日誌讀取等操做影響,致使整個修改耗時9.5個小時,產生書300GB+的日誌,對業務形成比較嚴重的影響。

--=====================================================================

推薦解決辦法:

建立新表,將數據導入到新表中,整個導入過程不影響業務訪問(在修改前業務已沒法插入數據,沒有寫操做,可是還有讀請求),數據導入完成後,創建對於索引,而後使用SP_RENAME修改表名。這樣能夠將業務影響下降到最低,而且導入數據能夠併發進行,提升導入效率,減少整個操做週期。

使用此推薦方法,用SSMS自帶的導入導入工具,約4個小時完成導入。

--======================================================================

我的猜測:

整個修改數據類型操做,是單線程操做,而且可能受單個log buffer每秒能產生的日誌記錄數限制,所以每秒寫入的日誌量較小,修改的行數比較少,致使整個修改操做持續大量時間。

--======================================================================

夜深了,妹子提神

相關文章
相關標籤/搜索