對線面試官:MySQL 給數(shù)據(jù)表增加一列,一定會鎖表嗎?
一、鎖的概念
1.1 鎖的分類
鎖的分類可以從多個方面來劃分。
圖片
圖片
從對數(shù)據(jù)操作類型分
- 讀鎖(共享鎖) : 針對同一份數(shù)據(jù),多個讀操作可以同時進(jìn)行而不會互相影響。
- 寫鎖(排它鎖) : 當(dāng)前寫操作沒有完成前,它會阻斷其他寫鎖和讀鎖。
從對數(shù)據(jù)操作粒度分
- 表鎖
- 行鎖
表鎖也是是InnoDB存儲引擎中的一種鎖機制,用于控制對表的并發(fā)訪問。InnoDB表鎖包括共享鎖(Shared Lock)和排他鎖(Exclusive Lock),用于實現(xiàn)不同程度的并發(fā)讀寫操作。嚴(yán)格意義上來說,InnoDB存儲引擎沒有MyISAM存儲引擎那種直接的完整的表級鎖。
1.2 InnoDB表鎖的特點和使用方式
圖片
圖片
- InnoDB表鎖是自動隱式鎖定的,不需要手動指定。
- InnoDB存儲引擎默認(rèn)采用行級鎖(Row-Level Locking)而不是表級鎖。這意味著在InnoDB中,鎖定的粒度更細(xì),可以同時支持并發(fā)讀寫操作,減少了鎖沖突和阻塞的可能性。
- InnoDB采用多版本并發(fā)控制(MVCC)機制,讀取操作不會阻塞寫入操作,寫入操作也不會阻塞讀取操作,提高了并發(fā)性能。
- InnoDB表鎖在事務(wù)中使用,并且鎖的持有時間盡可能短,以減少阻塞和沖突的可能性。
- InnoDB表鎖的具體行為受到事務(wù)的隔離級別和鎖定模式的影響。通過設(shè)置合適的隔離級別和鎖定模式,可以平衡并發(fā)性能和數(shù)據(jù)一致性的要求。
二、給數(shù)據(jù)表增加一列,一定會鎖表嗎?
在 MySQL 中,使用 InnoDB 存儲引擎給數(shù)據(jù)表增加一列時,并不一定會鎖表。InnoDB 存儲引擎提供了一些機制來減少對表的鎖定,以提高并發(fā)性能。
2.1 MySQL 5.6 會不會鎖表
從 MySQL 5.6 版本開始,InnoDB 引擎引入了在線數(shù)據(jù)定義語言(DDL)操作,其中包括對表結(jié)構(gòu)的修改。這些在線 DDL 操作允許在不鎖定整個表的情況下進(jìn)行結(jié)構(gòu)更改。具體來說,以下是可能的情況:
- 對于增加非空列: 在 InnoDB 中,增加非空列時,會執(zhí)行一個快速的元數(shù)據(jù)操作,不會鎖定整個表。這意味著在修改期間,其他會話可以繼續(xù)讀取和寫入表數(shù)據(jù)。
- 對于增加可為空列: 在 InnoDB 中,增加可為空列時,也會執(zhí)行一個快速的元數(shù)據(jù)操作,不會鎖定整個表。其他會話可以繼續(xù)讀取和寫入表數(shù)據(jù),但在修改期間,可能會有一些短暫的行鎖定。
?
注意:盡管 InnoDB 存儲引擎提供了較少的鎖定,但在執(zhí)行 ALTER TABLE 語句時仍可能會有一些性能影響。這可能是由于內(nèi)部的元數(shù)據(jù)操作、數(shù)據(jù)重組或日志寫入等引起的。
?
因此,在對大型表進(jìn)行結(jié)構(gòu)修改時,仍建議在低負(fù)載時執(zhí)行,以最小化對應(yīng)用程序的影響。
針對上面的問題,MySQL8.0做了更多的優(yōu)化和升級
2.2 MySQL 8.0 會不會鎖表
MySQL 8.0 在處理大數(shù)據(jù)表增加字段的情況下進(jìn)行了一些優(yōu)化,進(jìn)一步優(yōu)化了減少對表的鎖定時間和降低性能影響。在MySQL8.0中,還引入了Invisible Indexes、Instant DDL和In-Place Alter升級等新功能,可以進(jìn)一步提高M(jìn)ySQL的性能和可維護(hù)性。
- 原子 DDL: MySQL 8.0 引入了原子 DDL(Atomic DDL)操作,這意味著 ALTER TABLE 語句的執(zhí)行過程中將會有更少的阻塞。在增加字段的情況下,原子 DDL 機制可以減少對表的鎖定時間,并允許其他會話繼續(xù)讀取和寫入數(shù)據(jù)。
- 立即更新元數(shù)據(jù): MySQL 8.0 在增加字段時立即更新表的元數(shù)據(jù),而不需要等待整個操作完成。這樣可以更快地完成 ALTER TABLE 操作,并減少對表的鎖定時間。
- InnoDB 引擎優(yōu)化: MySQL 8.0 的 InnoDB 存儲引擎針對大數(shù)據(jù)表的結(jié)構(gòu)修改進(jìn)行了一些優(yōu)化。例如,對于增加非空字段,InnoDB 不再需要復(fù)制整個表的數(shù)據(jù)。相反,它會使用一種更輕量級的操作來添加新字段,從而減少鎖定時間和資源消耗。
- 增量元數(shù)據(jù)更新: MySQL 8.0 引入了增量元數(shù)據(jù)更新,這意味著在 ALTER TABLE 操作期間只需更新受影響的元數(shù)據(jù)信息,而不是整個表。這樣可以減少鎖定時間和操作的開銷。
三、總結(jié)
總結(jié)上面的所有內(nèi)容,實際就是單純的增加一個字段,表結(jié)構(gòu)修改和索引添加通常不會鎖定整個表,在某些情況下,MySQL可能需要鎖定整個表。同時數(shù)據(jù)量過大的時候,會出現(xiàn)一些性能問題,所以我們實際操作的過程中,一定要關(guān)注表的數(shù)據(jù)多小,最終的數(shù)據(jù)大?。ㄟ@里要關(guān)注索引數(shù)據(jù))。