1、簡介
MySQL 8.0 將數據庫元信息都存放於InnoDB存儲引擎表中,在之前版本的MySQL中,數據字典不僅僅存放於特定的存儲引擎表中,還存放於元數據文件、非事務性存儲引擎表中。本文將會介紹MySQL 8.0對數據字典的改進,以及改進帶來的好處、影響以及局限性。
2、數據字典
2.1、新版本之前的數據字典
數據字典是數據庫重要的組成部分之一,那么什么是數據字典?數據字典包含哪些內容呢?數據字典是對數據庫中的數據、庫對象、表對象等的元信息的集合。在MySQL中,數據字典信息內容就包括表結構、數據庫名或表名、字段的數據類型、視圖、索引、表字段信息、存儲過程、觸發器等內容。MySQL INFORMATION_SCHEMA庫提供了對數據局元數據、統計信息、以及有關MySQL server的訪問信息(例如:數據庫名或表名,字段的數據類型和訪問權限等)。該庫中保存的信息也可以稱為MySQL的數據字典。
在MySQL8.0之前,MySQL的數據字典信息,並沒有全部存放在系統數據庫表中,部分數據庫數據字典信息存放於文件中,其余的數據字典信息存放於數據字典庫中(INFORMATION_SCHEMA,mysql,sys)。例如表結構信息存放在.frm文件中,數據庫表字段信息存放於INFORMATION_SCHEMA下的COLUMNS表中。早期,5.6版本之前,MyISAM是MySQL的默認存儲引擎,而作為MyISAM存儲引擎,它是沒有數據字典的。只有表結構信息記錄在.frm文件中。MySQL5.6版本之后,將InnoDB存儲引擎作為默認的存儲引擎。在InnoDB存儲引擎中,添加了一些數據字典文件用於存放數據字典元信息,例如:.opt文件,記錄了每個庫的一些基本信息,包括庫的字符集等信息,.TRN,.TRG文件用於存放觸發器的信息內容。
2.2、新版本數據字典的改進
最新的MySQL 8.0 發布之后,對數據庫數據字典方面做了較大的改進。
- 首先是,將所有原先存放於數據字典文件中的信息,全部存放到數據庫系統表中,即將之前版本的
.frm,.opt,.par,.TRN,.TRG,.isl文件都移除了,不再通過文件的方式存儲數據字典信息。 - 其次是對INFORMATION_SCHEM,mysql,sys系統庫中的存儲引擎做了改進,原先使用MyISAM存儲引擎的數據字典表都改為使用InnoDB存儲引擎存放。從不支持事務的MyISAM存儲引擎轉變到支持事務的InnoDB存儲引擎,為原子DDL的實現,提供了可能性。
3、新數據字典帶來的影響
3.1、INFORMATION_SCHEMA性能提升
8.0中對數據字典進行改進之后,很大程度上提高了對INFORMATIONS_SCHEMA的查詢性能,通過可以通過查表快速的獲得想要查詢的數據,原因是:
- 數據庫在查詢INFORMATION_SCHEMA的表時,不再一定需要創建一張臨時表,可以直接查詢數據字典表。
- 在之前版本中,數據字典信息不一定是存放於表中,所以在獲取數據字典信息時候,不僅僅是查表操作。例如讀取數據庫表結構信息,底層其實是讀取.frm文件來獲得,是一個文件打開讀取的操作。而在新版本中,數據字典信息都可以通過直接查表的方式獲取,替代那些獲取信息慢的方式。
- 對存儲引擎的改進之后,在查詢INFORMATIONS_SCHEMA表時,如果表上有索引,優化器會合理的利用索引。
- 對於INFORMATION_SCHEMA下的STATISTICS表和TABLES表中的信息,8.0中通過緩存的方式,以提高查詢的性能。可以通過設置information_schema_stats_expiry參數設置緩存數據的過期時間,默認是86400秒。查詢這兩張表的數據的時候,首先是到緩存中進行查詢,緩存中沒有緩存數據,或者緩存數據過期了,查詢會從存儲引擎中獲取最新的數據。如果需要獲取最新的數據,可以通過設置information_schema_stats_expiry參數為0或者ANALYZE TABLE操作。
3.2、原子DDL
MySQL8.0開始支持原子DDL操作,一個原子DDL操作,具體的操作內容包括:數據字典更新,存儲引擎層的操作,在binlog中記錄DDL操作。並且這些操作都是原子性的,表示中間過程出現錯誤的時候,是可以完整回退的。這在之前版本的DDL操作中是不支持的。之前數據庫版本中一直沒有支持原子DDL的特性,是有原因的,因為在早期的數據庫版本中,數據庫元信息存放於元信息文件中、非事務性表中以及特定存儲引擎的數據字典中。這些都無法保證DDL操作內容在一個事務當中,無法保證原子性。
具體的原子DDL,后續會有專門的文章。
3.3、innodb_read_only對所有存儲引擎生效
在8.0之前版本中,innodb_read_only參數可以阻止對InnoDB存儲引擎表的create和drop等更新操作。但是在MySQL8.0中,開啟innodb_read_only參數阻止了所有存儲引擎的這些操作。create或者drop表的操作都需要更新數據字典表,8.0中這個數據字典表都改為了InnoDB存儲引擎,所以對於數據字典表的更新會失敗,從而導致各存儲引擎create和drop表失敗。同樣的像ANALYZE TABLE和ALTER TABLE tbl_name ENGINE=engine_name這種操作也會失敗,因為這些操作都要去更新數據字典表。
3.4、mysqldump mysqlpump導出的內容影響
MySQL8.0之后,在使用mysqldump和mysqlpump導出數據時候,與之前有了一些不同,主要是以下幾點:
- 之前版本的mysqldump和mysqlpump可以導出mysql系統庫中的所有表的內容,8.0之后,只能導出mysql系統庫中的非data dictionary table。(data dictionary table內容可以參照:https://dev.mysql.com/doc/refman/8.0/en/system-database.html#system-database-data-dictionary-tables)
- 之前版本當使用–all-databases參數導出數據的時候,不加–routines和–events選項也可以導出觸發器、存儲過程等信息,因為這些信息都存放於proc和event表中,導出所有表即可導出這些信息。但是在8.0中,proc表和event表都不再使用,並且定義觸發器、存儲過程的數據字典表不會被導出,所以在8.0中使用mysqldump、mysqlpump導出數據的時候,如果需要導出觸發器、存儲過程等內容,一定需要加上–routines和–events選項。
- 之前版本中–routines選項導出的時候,備份賬戶需要有proc表的SELECT權限,在8.0中需要對所有表的SELECT權限
- 之前版本中,導出觸發器、存儲過程可以同時導出觸發器、存儲過程的創建和修改的時間戳,8.0中不再支持。
3.5、新數據字典的局限性
MySQL8.0數據字典的改進有很多方便的特性,例如帶來了原子DDL,提升了INFORMATION_SCHEMA的查詢性能等,但是它並不是完美的,新版數據字典還是存在一些局限性: - 通過手動mkdir的方式在數據目錄下創建庫目錄,這種方式是不會被數據庫所識別到。
- DDL操作會花費更長的時間,因為之前的DDL操作是直接對.frm文件進行更改操作,只要寫一個文件,現在是需要更新數據字典表,代表着需要將數據寫到存儲引擎、read log、undo log中。
