MySQL數(shù)據(jù)庫(kù)線上修改表結(jié)構(gòu)的方法
一、MDL元數(shù)據(jù)鎖
在修改表結(jié)構(gòu)之前,先來(lái)看下可能存在的問(wèn)題。
1、什么是MDL鎖
MySQL有一個(gè)把鎖,叫做MDL元數(shù)據(jù)鎖,當(dāng)對(duì)表修改的時(shí)候,會(huì)自動(dòng)給表加上這把鎖,也就是不需要自己顯式使用。
- 當(dāng)對(duì)表做增刪改查的時(shí)候,加的是MDL讀鎖
- 當(dāng)對(duì)表結(jié)構(gòu)做變更修改的時(shí)候,加的是MDL寫(xiě)鎖
讀與讀之間不互斥,讀與寫(xiě),寫(xiě)與寫(xiě)之間互斥,因此
- 當(dāng)有一個(gè)線程對(duì)表執(zhí)行增刪蓋茶的時(shí)候,會(huì)阻塞掉別的線程對(duì)表結(jié)構(gòu)修改的請(qǐng)求
- 當(dāng)有一個(gè)線程對(duì)表結(jié)構(gòu)修改的時(shí)候,會(huì)阻塞掉別的線程對(duì)表增刪改查的請(qǐng)求
2、MDL鎖的問(wèn)題
并且MDL一旦上鎖之后,只有當(dāng)前請(qǐng)求的事務(wù)提交才會(huì)釋放,如果是一個(gè)長(zhǎng)事務(wù),或者是線上數(shù)據(jù)量很大,修改表結(jié)構(gòu)默認(rèn)上了MDL寫(xiě)鎖,會(huì)很耗時(shí)一直阻塞掉后邊其他請(qǐng)求。
想象一種場(chǎng)景,A(select),B(alter), C(select),D(select).....分別為按照順序?qū)ySQL同一張表的請(qǐng)求,這些請(qǐng)求會(huì)形成一個(gè)隊(duì)列。
當(dāng)A(select)獲取表的MDL讀鎖之后,就會(huì)阻塞掉B(alter),因?yàn)锽要加的是MDL寫(xiě)鎖,B被阻塞掉之后,就會(huì)導(dǎo)致后邊等待隊(duì)列中的其他請(qǐng)求都被阻塞掉,最終造成Mysql的可用連接耗盡,請(qǐng)求超時(shí)等問(wèn)題。
二、如何線上修改MySQL表結(jié)構(gòu)
鑒于以上MDL鎖,得知對(duì)表做alter修改結(jié)構(gòu)很會(huì)阻塞掉其他的正常請(qǐng)求,所以修改操作要放在非業(yè)務(wù)高峰期來(lái)做,一般是放到凌晨2-4點(diǎn)。
具體步驟:
- 對(duì)表加讀寫(xiě)鎖,使得此時(shí)表只讀、
- 復(fù)制原表的物理結(jié)構(gòu)
- 修改新表的物理結(jié)構(gòu),包括增加新字段或者修改其他表結(jié)構(gòu)
- 把表結(jié)構(gòu)導(dǎo)入新表,數(shù)據(jù)同步完成,鎖住中間表,刪除原表
- 將新表rename為原表名
- 釋放鎖
以上方案的問(wèn)題是,數(shù)據(jù)量很大的時(shí)候,數(shù)據(jù)都導(dǎo)入需要時(shí)間,這個(gè)過(guò)程中,服務(wù)是不可訪問(wèn)的。
改進(jìn):
新建一張表 A_new,其比原表多了幾個(gè)字段,通過(guò)數(shù)據(jù)訂閱的方式訂閱原表A,把線上的表A中的數(shù)據(jù)同步到這個(gè)新建的表A_new中,這個(gè)過(guò)程會(huì)一直持續(xù),并且這個(gè)過(guò)程中表A是可以增刪改查的,總有一個(gè)時(shí)刻,這兩張表的數(shù)據(jù)是完全同步的,數(shù)據(jù)上是沒(méi)有任何差異的,這個(gè)時(shí)候把原表表名A給修改掉,把新表A_new修改為原表A,這個(gè)操作是一個(gè)短暫操作,可以瞬間完成,不會(huì)有很大影響。
優(yōu)缺點(diǎn):
- 好處是同步的過(guò)程不會(huì)影響原有的業(yè)務(wù)正常。
- 缺點(diǎn)是過(guò)程中需要額外一倍的存儲(chǔ)空間去存儲(chǔ)這個(gè)新表,當(dāng)rename完成之后,可以把老表刪掉。
到此這篇關(guān)于MySQL數(shù)據(jù)庫(kù)線上修改表結(jié)構(gòu)的方法的文章就介紹到這了,更多相關(guān)mysql線上修改表結(jié)構(gòu)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MySQL查詢數(shù)據(jù)庫(kù)所有表名以及表結(jié)構(gòu)其注釋(小白專用)
- mysql將數(shù)據(jù)庫(kù)中所有表結(jié)構(gòu)和數(shù)據(jù)導(dǎo)入到另一個(gè)庫(kù)的方法(親測(cè)有效)
- 利用Python批量導(dǎo)出mysql數(shù)據(jù)庫(kù)表結(jié)構(gòu)的操作實(shí)例
- mysql如何比對(duì)兩個(gè)數(shù)據(jù)庫(kù)表結(jié)構(gòu)的方法
- MYSQL數(shù)據(jù)庫(kù)表結(jié)構(gòu)優(yōu)化方法詳解
- 詳解 linux mysqldump 導(dǎo)出數(shù)據(jù)庫(kù)、數(shù)據(jù)、表結(jié)構(gòu)
- mysql如何將數(shù)據(jù)庫(kù)中的所有表結(jié)構(gòu)和數(shù)據(jù)導(dǎo)入到另一個(gè)庫(kù)
相關(guān)文章
MySql,MVCC實(shí)現(xiàn)及其機(jī)制,快照讀在RC,RR下的區(qū)別說(shuō)明
這篇文章主要介紹了MySql,MVCC實(shí)現(xiàn)及其機(jī)制,快照讀在RC,RR下的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04MySQL5.7.18主從復(fù)制搭建(一主一從)教程詳解
MySQL使用3個(gè)線程來(lái)執(zhí)行復(fù)制功能(其中1個(gè)在主服務(wù)器上,另兩個(gè)在從服務(wù)器上。這篇文章主要介紹了MySQL5.7.18主從復(fù)制搭建(一主一從)教程詳解,需要的朋友可以參考下2017-08-08MySQL 客戶端不輸入用戶名和密碼直接連接數(shù)據(jù)庫(kù)的2個(gè)方法
MySQL 客戶端不輸入用戶名和密碼直接連接數(shù)據(jù)庫(kù)的2個(gè)方法,大家可以測(cè)試下。2009-07-07MySQL從MyISAM轉(zhuǎn)換成InnoDB錯(cuò)誤與常用解決辦法
由于一些程序的要求,需要MyISAM數(shù)據(jù)引擎或InnoDB,下面是具體的解決方法,經(jīng)測(cè)試偶爾會(huì)出現(xiàn)一些問(wèn)題。2011-05-05Navicat for MySql可視化導(dǎo)入CSV文件
這篇文章主要為大家詳細(xì)介紹了Navicat for MySql可視化導(dǎo)入CSV文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05mysql下普通用戶備份數(shù)據(jù)庫(kù)時(shí)無(wú)lock tables權(quán)限的解決方法
mysql使用普通用戶備份出現(xiàn)無(wú)lock tables權(quán)限的解決方法,需要的朋友可以參考下。2011-10-10MySQL Sleep連接過(guò)多問(wèn)題解決方法
這篇文章主要介紹了MySQL Sleep連接過(guò)多問(wèn)題解決方法,MySQL Sleep連接過(guò)多一般多為客戶端沒(méi)關(guān)閉連接導(dǎo)致的,解決方法很簡(jiǎn)單,修改一下配置文件即可,需要的朋友可以參考下2015-05-05