MySQL 8.0 20個 InnoDB 及資料字典相關的新特性
本篇將聚焦於 MySQL 8.0 InnoDB 及資料字典相關的新特性。這些新特性涉及的範圍包括:Redo log、事務排程演算法、自增主鍵、回滾表空間、死鎖、臨時表空間、Doublewrite Buffer、資料字典、原子 DDL、information_schema、備份等。
1. Redo log 的最佳化
相關的最佳化有:
對 redo log 進行了無鎖設計 允許多個使用者執行緒併發寫入 redo log buffer 可動態修改 innodb_log_buffer_size 的大小
2. 事務排程演算法
當有多個事務競爭同一把鎖時,在 MySQL 8.0 之前,使用的是 FIFO(First In First Out,先進先出)演算法,該演算法會將鎖優先分配給最先請求的事務。
在 MySQL 8.0 中,引入了 CATS (Contention-Aware Transaction Scheduling,競爭感知事務排程)演算法,該演算法會計算每個事務阻塞的事務數,然後將鎖優先分配給阻塞事務最多的事務。
3. 自增主鍵的持久化
在 MySQL 8.0 之前,自增主鍵的分配是由 InnoDB 資料字典內部一個計數器來決定的。該計數器只在記憶體中維護,並不會持久化到磁碟中。
當資料庫重啟後,會基於自增主鍵的最大值(假設是 max_id)來重新初始化自增主鍵。
所以如果 max_id 之後的自增主鍵值分配但又刪除了,則資料庫重啟後,會繼續從 max_id + 1 開始分配自增主鍵值。
這就意味著,之前分配的自增主鍵值(雖然被刪除了)又被重新分配了。
當然,大多數情況下也沒有問題,不過在以下兩種場景需要注意:
業務將自增主鍵作為業務主鍵。在使用的過程中可能會發現兩筆不同的訂單對應著同一個業務主鍵。
歸檔場景。在歸檔的過程中有可能會出現主鍵衝突。
具體細節可參考:MySQL 8 新特性之自增主鍵的持久化
4. 預設開啟回滾表空間
在 MySQL 5.7 中,因 innodb_undo_tablespaces 預設為 0,所以回滾表空間預設是沒有開啟的。若要開啟,只能在初始化時將 innodb_undo_tablespaces 設定為非 0 值。
在 MySQL 8.0 中,innodb_undo_tablespaces 預設為 2。不僅如此,innodb_undo_tablespaces 還可線上動態修改。
從 MySQL 8.0.14 開始,支援透過 SQL 語句來管理回滾表空間。
# 新增回滾表空間,副檔名必須是.ibu。
CREATE UNDO TABLESPACE tablespace_name ADD DATAFILE 'file_name.ibu';
# 刪除回滾表空間。
DROP UNDO TABLESPACE tablespace_name;
# 在刪除回滾表空間之前,必須先將它設定為 INACTIVE 狀態。
ALTER UNDO TABLESPACE tablespace_name SET INACTIVE;
# 將回滾表空間設定為 ACTIVE 狀態。
ALTER UNDO TABLESPACE tablespace_name SET ACTIVE;
與此同時,innodb_undo_tablespaces 引數被棄用,雖然還是可以修改,但不起作用,innodb_undo_tablespaces 永遠為 2。
5. TempTable 引擎
預設的記憶體臨時表由 MEMORY 引擎更改為 TempTable 引擎,相比於前者,後者支援以變長方式儲存 VARCHAR、VARBINARY 等變長欄位。
從 MySQL 8.0.13 開始,TempTable 引擎支援 BLOB 欄位。
6. innodb_dedicated_server
引入了 innodb_dedicated_server 引數,可基於伺服器的記憶體動態設定 innodb_buffer_pool_size、innodb_redo_log_capacity 和 innodb_flush_method。
7. 關閉死鎖檢測
引入了 innodb_deadlock_detect 引數關閉死鎖檢測。
8. 線上回收臨時表空間的磁碟空間
在 MySQL 5.7 中,使用者建立的臨時表和磁碟臨時表會儲存在全域性臨時表空間(ibtmp1)中。
ibtmp1 一旦增長,就不會收縮。如果要回收 ibtmp1 的空間,就只能重啟例項。
在 MySQL 8.0 中,使用者建立的臨時表和磁碟臨時表會儲存在會話臨時表空間中。會話臨時表空間預設位於 #innodb_temp 目錄下。
一個會話最多會分配兩個臨時表空間,分別用來儲存使用者臨時表和磁碟臨時表。當會話的連線斷開時,會清空這兩個臨時表空間。
9. 設定獨立的雙寫緩衝區(Doublewrite Buffer)
在 MySQL 8.0.20 之前,雙寫緩衝區預設儲存在 InnoDB 系統表空間(ibdata1)中。
從 MySQL 8.0.20 開始,雙寫緩衝區會儲存在單獨的 #ib_16384_0.dblwr 和 #ib_16384_1.dblwr 檔案中。
從 MySQL 8.0.30 開始,innodb_doublewrite 在 ON(開啟雙寫緩衝區) 和 OFF(關閉雙寫緩衝區) 的基礎上新增了兩個選項:
DETECT_AND_RECOVER:作用與 ON 一樣(實際上是 ON 的同義詞)。
在進行髒頁重新整理時,會首先將資料頁寫到雙寫緩衝區中。在進行故障恢復時,會透過雙寫緩衝區來修復資料檔案中不完整的資料頁。
DETECT_ONLY:也會開啟雙寫緩衝區,只不過在進行髒頁重新整理時,只會記錄資料頁的後設資料資訊,不會儲存資料頁的內容。
所以在進行故障恢復時,即使資料檔案中存在不完整的資料頁,也不能透過雙寫緩衝區來修復。
該選項主要是用來檢測例項啟動時是否有不完整的資料頁。
10. 禁用重做日誌記錄(redo logging)
在 MySQL 8.0.21 開始,可以使用 ALTER INSTANCE DISABLE INNODB REDO_LOG 命令禁用重做日誌記錄。
該特性適用於資料載入場景,線上生產環境切記不要禁用。
禁用後,可透過 ALTER INSTANCE ENABLE INNODB REDO_LOG 命令開啟。
11. 檢視錶快取在 Buffer Pool 中資料頁的數量
可透過 information_schema.innodb_cached_indexes 檢視錶快取在 Buffer Pool 中資料頁的數量。
SELECT
tables.name, indexes.name, cached.n_cached_pages
FROM
information_schema.innodb_cached_indexes AS cached,
information_schema.innodb_indexes AS indexes,
information_schema.innodb_tables AS tables
WHERE
cached.index_id = indexes.index_id AND indexes.table_id = tables.table_id;
+------------+------------+----------------+
| table_name | index_name | n_cached_pages |
+------------+------------+----------------+
| db1/t1 | idx_c1 | 279 |
| db1/t1 | PRIMARY | 4756 |
+------------+------------+----------------+
2 rows in set (0.00 sec)
12. 動態調整 redo log 的容量
從 MySQL 8.0.30 開始,可透過 innodb_redo_log_capacity 引數來動態調整 redo log 的容量。
在 MySQL 8.0.30 之前,InnoDB 預設會在資料目錄下建立兩個 redo log。Redo log 的數量和大小分別由 innodb_log_files_in_group 和 innodb_log_file_size 決定。
隨著 innodb_redo_log_capacity 的引入,InnoDB 會在資料目錄的 #innodb_redo 目錄下建立 32 個 redo log。Redo log 的總大小由 innodb_redo_log_capacity 決定。
innodb_redo_log_capacity 如果沒有顯式設定,則預設等於 innodb_log_file_size * innodb_log_files_in_group。
13. 基於 InnoDB 的資料字典
引入了原生的、基於 InnoDB 的資料字典。這些資料字典表位於 mysql 庫中,對使用者不可見。
如果是 debug 版本,可透過以下方式訪問資料字典表。
mysql> SET SESSION debug='+d,skip_dd_table_access_check';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT name, schema_id, hidden, type FROM mysql.tables WHERE schema_id=1 AND hidden='System';
+------------------------------+-----------+--------+------------+
| name | schema_id | hidden | type |
+------------------------------+-----------+--------+------------+
| catalogs | 1 | System | BASE TABLE |
| character_sets | 1 | System | BASE TABLE |
| check_constraints | 1 | System | BASE TABLE |
| collations | 1 | System | BASE TABLE |
...
+------------------------------+-----------+--------+------------+
32 rows in set (0.02 sec)
在 MySQL 8.0 中,mysql 庫中的 InnoDB 表(包括資料字典表)會儲存在資料目錄下的 mysql.ibd 檔案中,而其它非 InnoDB 表則依舊儲存在 mysql 目錄下。
[root@mysql data]# ls mysql
general_log_213.sdi general_log.CSM general_log.CSV slow_log_214.sdi slow_log.CSM slow_log.CSV
14. 移除了 frm 等檔案
移除了之前版本的 frm、par、TRN、TRG、isl、db.opt、ddl_log.log 等檔案,這些檔案會儲存部分後設資料資訊。
15. 不再識別手動建立的資料庫目錄
因為資料字典的引入,MySQL 不再識別手動建立的資料庫目錄。
看下面這個示例。
在 MySQL 5.7 例項的資料目錄下建立一個目錄,該目錄會被 MySQL 識別。
# cd /data/mysql/3307/data/
# mkdir test
mysql5.7> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)
mysql5.7> USE test
Database changed
mysql5.7> SHOW TABLES;
Empty set (0.00 sec)
相同的操作如果是在 MySQL 8.0 中執行,則不會識別。
16. 原子 DDL
在 MySQL 8.0 之前,後設資料資訊會儲存在多個檔案中。在進行 DDL 的過程中,如果例項異常重啟,可能會導致這些檔案中的後設資料資訊不一致,甚至產生 Orphan(孤兒)表。
MySQL 8.0 引入了原子 DDL,可將 DDL 操作相關的後設資料更新、儲存引擎操作和 binlog 寫入放到一個原子操作中。
這樣就能保證 DDL 操作要麼提交,要麼回滾,不存在任何中間狀態,即使 DDL 期間例項發生了重啟。
除此之外,一些 DDL 操作的行為也發生了變化,看下面這個示例。
# MySQL 5.7
mysql5.7> CREATE TABLE t1(id INT);
Query OK, 0 rows affected (0.02 sec)
# 雖然命令報錯了,但 t1 表還是被刪除了
mysql5.7> DROP TABLE t1,t2;
ERROR 1051 (42S02): Unknown table 'slowtech.t2'
mysql5.7> SHOW TABLES;
Empty set (0.00 sec)
# MySQL 8.0
mysql8.0> CREATE TABLE t1(id INT);
Query OK, 0 rows affected (0.03 sec)
# 命令報錯,t1 表沒被刪除
mysql8.0> DROP TABLE t1,t2;
ERROR 1051 (42S02): Unknown table 'slowtech.t2'
mysql8.0> SHOW TABLES;
+--------------------+
| Tables_in_slowtech |
+--------------------+
| t1 |
+--------------------+
1 row in set (0.00 sec)
17. SDI
資料庫物件的後設資料資訊除了儲存在資料字典中,也會再儲存一份 SDI(Serialized Dictionary Information,序列化的字典資訊)。
當資料字典不可用時,我們可以基於 SDI 提取物件的後設資料資訊。
對於 InnoDB 表,SDI 會儲存在 .ibd 檔案中,需透過 ibd2sdi 命令檢視。
對於其它儲存引擎的表,SDI 會儲存在 .sdi 檔案中,可直接透過 cat 命令檢視。
18. information_schema 查詢效能提升
information_schema 中的部分表已重構為基於資料字典的檢視,在此之前,這些表是透過臨時表來實現的。
information_schema.statistics 和 information_schema.tables 兩張表中表相關的統計資訊會快取起來以提升查詢效能。
快取的時間由 information_schema_stats_expiry 引數決定,預設是 86400 秒(24小時)。
如果要更新某張表的統計資訊,可執行 ANALYZE TABLE 操作。
19. information_schema 表中的列名會以大寫形式返回
查詢時,在沒有指定別名的情況下,返回的列名會與查詢指定的列名一致,包括大小寫也一樣。
看下面這個示例。
mysql> SELECT id FROM test.t1;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
mysql> SELECT Id FROM test.t1;
+----+
| Id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
在 MySQL 8.0 中,如果查詢的是 information_schema 中的表,則列名會以大寫形式返回。
# 無論查詢使用的是 table_name 還是 Table_Name,返回的列名都是 TABLE_NAME。
mysql8.0> SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'users';
+------------+
| TABLE_NAME |
+------------+
| users |
+------------+
1 row in set (0.00 sec)
mysql8.0> SELECT Table_Name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'users';
+------------+
| TABLE_NAME |
+------------+
| users |
+------------+
1 row in set (0.00 sec)
20. 備份
在 MySQL 8.0 之前,在使用 mysqldump 或 mysqlpump 進行全庫備份(--all-databases)時,即使沒有指定 --routines 和 --events,也會備份儲存過程(包括自定義函式)和定時器。
之所以會這樣,是因為這兩類物件的定義資訊是儲存在 mysql.proc 和 mysql.event 表中。當進行全庫備份時,會備份 mysql 庫中的所有表,自然也包括 mysql.proc 和 mysql.event。
在 MySQL 8.0 中,沒有 mysql.proc 和 mysql.event 表,取而代之的是 mysql.routines 和 mysql.events。注意,替換後的表是資料字典表,對使用者是不可見的。
所以,在 MySQL 8.0 中,如果要備份儲存過程和定時器,需顯式指定 --routines 和 --events。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024924/viewspace-2935957/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL 8.0 18個管理相關的新特性MySql
- MySQL 8.0 之資料字典MySql
- MySQL 8.0 新特性MySql
- MySQL 8.0 在關聯式資料庫方面有這些新特性MySql資料庫
- MySQL 8.0新特性概覽MySql
- MySQL 8.0新特性-並行查詢innodb_parallel_read_threadsMySql並行Parallelthread
- 字典及相關操作
- PL/SQL相關的資料字典SQL
- MySQL8.0-新特性彙總MySql
- MySQL8.0-新特性-DescendingIndexMySqlIndex
- MySQL 8.0 新特性梳理彙總MySql
- MySQL·8.0新特性·InvisibleIndexMySqlIndex
- MySQL 8.0新特性更新介紹MySql
- MySQL關於資料字典的一個疑問MySql
- InnoDB資料字典--字典表載入
- python的字典及相關操作Python
- Oracle相關資料字典檢視Oracle
- MySQL8.0 新特性 top10MySql
- Mysql8.0部分新特性MySql
- mysql8.0新特性--隱藏索引MySql索引
- MySQL8.0新特性-臨時表的改善MySql
- 解讀MySQL 8.0資料字典快取管理機制MySql快取
- 解讀MySQL 8.0資料字典的初始化與啟動MySql
- MySQL 8.0新特性-倒敘索引 desc indexMySql索引Index
- MySQL8.0新特性-CTE語法支援MySql
- MySQL·8.0新特性·Newdatadictionary嚐鮮篇MySql
- MySQL8.0 新特性:Partial Update of LOB ColumnMySql
- 好程式設計師大資料培訓分享MySQL8.0新特性程式設計師大資料MySql
- 新特性解讀 | MySQL 8.0 對 UNION 的改進MySql
- mysql innodb相關引數說明MySql
- 幾個和MySQL InnoDB相關的引數設定說明MySql
- 8.0新特性-並行查詢innodb_parallel_read_threads並行Parallelthread
- Oracle 21c新特性預覽與日常管理相關的幾個新特性Oracle
- MySQL資料庫部署及初始化相關MySql資料庫
- MySQL 8.0 新增特性MySql
- 系統許可權相關資料字典
- WebView的基本使用及相關特性WebView
- MySQL的幾個和innodb相關的主要引數設定總結MySql