共計 16715 個字符,預計需要花費 42 分鐘才能閱讀完成。
本篇內容主要講解“MySQL8.0 新特性是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“MySQL8.0 新特性是什么”吧!
1. 默認字符集由 latin1 變為 utf8mb4
在 8.0 版本之前,默認字符集為 latin1,utf8 指向的是 utf8mb3,8.0 版本默認字符集為 utf8mb4,utf8 默認指向的也是 utf8mb4。注:在 Percona Server 8.0.15 版本上測試,utf8 仍然指向的是 utf8mb3,與官方文檔有出入。
Warning | 3719 | utf8 is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous. |
2. MyISAM 系統表全部換成 InnoDB 表
系統表全部換成事務型的 innodb 表,默認的 MySQL 實例將不包含任何 MyISAM 表,除非手動創建 MyISAM 表。
# MySQL 5.7
mysql select distinct(ENGINE) from information_schema.tables;
+——————–+
| ENGINE |
+——————–+
| MEMORY |
| InnoDB |
| MyISAM |
| CSV |
| PERFORMANCE_SCHEMA |
| NULL |
+——————–+
6 rows in set (0.00 sec)
# MySQL 8.0
mysql select distinct(ENGINE) from information_schema.tables;
+——————–+
| ENGINE |
+——————–+
| NULL |
| InnoDB |
| CSV |
| PERFORMANCE_SCHEMA |
+——————–+
4 rows in set (0.00 sec)
3. 自增變量持久化
在 8.0 之前的版本,自增主鍵 AUTO_INCREMENT 的值如果大于 max(primary key)+1,在 MySQL 重啟后,會重置 AUTO_INCREMENT=max(primary key)+1,這種現象在某些情況下會導致業務主鍵沖突或者其他難以發現的問題。自增主鍵重啟重置的問題很早就被發現,一直到 8.0 才被解決,8.0 版本將會對 AUTO_INCREMENT 值進行持久化,MySQL 重啟后,該值將不會改變。
4. DDL 原子化
InnoDB 表的 DDL 支持事務完整性,要么成功要么回滾,將 DDL 操作回滾日志寫入到 data dictionary 數據字典表 mysql.innodb_ddl_log 中用于回滾操作,該表是隱藏的表,通過 show tables 無法看到。通過設置參數,可將 ddl 操作日志打印輸出到 mysql 錯誤日志中。
mysql set global log_error_verbosity=3;
mysql set global innodb_print_ddl_logs=1;
mysql create table t1(c int) engine=innodb;
# MySQL 錯誤日志:
2019-06-26T11:25:25.817245+08:00 44 [Note] [MY-012473] [InnoDB] InnoDB: DDL log insert : [DDL record: DELETE SPACE, id=41, thread_id=44, space_id=6, old_file_path=./db/t1.ibd]
2019-06-26T11:25:25.817369+08:00 44 [Note] [MY-012478] [InnoDB] InnoDB: DDL log delete : by id 41
2019-06-26T11:25:25.819753+08:00 44 [Note] [MY-012477] [InnoDB] InnoDB: DDL log insert : [DDL record: REMOVE CACHE, id=42, thread_id=44, table_id=1063, new_file_path=db/t1]
2019-06-26T11:25:25.819796+08:00 44 [Note] [MY-012478] [InnoDB] InnoDB: DDL log delete : by id 42
2019-06-26T11:25:25.820556+08:00 44 [Note] [MY-012472] [InnoDB] InnoDB: DDL log insert : [DDL record: FREE, id=43, thread_id=44, space_id=6, index_id=140, page_no=4]
2019-06-26T11:25:25.820594+08:00 44 [Note] [MY-012478] [InnoDB] InnoDB: DDL log delete : by id 43
2019-06-26T11:25:25.825743+08:00 44 [Note] [MY-012485] [InnoDB] InnoDB: DDL log post ddl : begin for thread id : 44
2019-06-26T11:25:25.825784+08:00 44 [Note] [MY-012486] [InnoDB] InnoDB: DDL log post ddl : end for thread id : 44
來看另外一個例子,庫里只有一個 t1 表,drop table t1,t2; 試圖刪除 t1,t2 兩張表, 在 5.7 中,執行報錯,但是 t1 表被刪除,在 8.0 中執行報錯,但是 t1 表沒有被刪除,證明了 8.0 DDL 操作的原子性,要么全部成功,要么回滾。
# MySQL 5.7
mysql show tables;
+—————+
| Tables_in_db |
+—————+
| t1 |
+—————+
1 row in set (0.00 sec)
mysql drop table t1, t2;
ERROR 1051 (42S02): Unknown table db.t2
mysql show tables;
Empty set (0.00 sec)
# MySQL 8.0
mysql show tables;
+—————+
| Tables_in_db |
+—————+
| t1 |
+—————+
1 row in set (0.00 sec)
mysql drop table t1, t2;
ERROR 1051 (42S02): Unknown table db.t2
mysql show tables;
+—————+
| Tables_in_db |
+—————+
| t1 |
+—————+
1 row in set (0.00 sec)
5. 參數修改持久化
MySQL 8.0 版本支持在線修改全局參數并持久化,通過加上 PERSIST 關鍵字,可以將修改的參數持久化到新的配置文件(mysqld-auto.cnf)中,重啟 MySQL 時,可以從該配置文件獲取到最新的配置參數。例如執行:set PERSIST expire_logs_days=10 ; 系統會在數據目錄下生成一個包含 json 格式的 mysqld-auto.cnf 的文件,格式化后如下所示,當 my.cnf 和 mysqld-auto.cnf 同時存在時,后者具有更高優先級。
{
Version : 1,
mysql_server : {
expire_logs_days : {
Value : 10 ,
Metadata : {
Timestamp : 1529657078851627,
User : root ,
Host : localhost
}
}
}
}
6. 新增降序索引
MySQL 在語法上很早就已經支持降序索引,但實際上創建的仍然是升序索引,如下 MySQL 5.7 所示,c2 字段降序,但是從 show create table 看 c2 仍然是升序。8.0 可以看到,c2 字段降序。
# MySQL 5.7
mysql create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));
Query OK, 0 rows affected (0.03 sec)
mysql show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL,
KEY `idx_c1_c2` (`c1`,`c2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
# MySQL 8.0
mysql create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));
Query OK, 0 rows affected (0.06 sec)
mysql show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL,
KEY `idx_c1_c2` (`c1`,`c2` DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC
1 row in set (0.00 sec)
再來看看降序索引在執行計劃中的表現,在 t1 表插入 10 萬條隨機數據,查看 select * from t1 order by c1 , c2 desc; 的執行計劃。從執行計劃上可以看出,5.7 的掃描數 100113 遠遠大于 8.0 的 5 行,并且使用了 filesort。
DELIMITER ;;
CREATE PROCEDURE test_insert ()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i 100000
DO
insert into t1 select rand()*100000, rand()*100000;
SET i=i+1;
END WHILE ;
commit;
END;;
DELIMITER ;
CALL test_insert();
# MySQL 5.7
mysql explain select * from t1 order by c1 , c2 desc limit 5;
+—-+————-+——-+————+——-+—————+———–+———+——+——–+———-+—————————–+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——-+—————+———–+———+——+——–+———-+—————————–+
| 1 | SIMPLE | t1 | NULL | index | NULL | idx_c1_c2 | 10 | NULL | 100113 | 100.00 | Using index; Using filesort |
+—-+————-+——-+————+——-+—————+———–+———+——+——–+———-+—————————–+
1 row in set, 1 warning (0.00 sec)
# MySQL 8.0
mysql explain select * from t1 order by c1 , c2 desc limit 5;
+—-+————-+——-+————+——-+—————+———–+———+——+——+———-+————-+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——-+—————+———–+———+——+——+———-+————-+
| 1 | SIMPLE | t1 | NULL | index | NULL | idx_c1_c2 | 10 | NULL | 5 | 100.00 | Using index |
+—-+————-+——-+————+——-+—————+———–+———+——+——+———-+————-+
1 row in set, 1 warning (0.00 sec)
降序索引只是對查詢中特定的排序順序有效,如果使用不當,反而查詢效率更低,比如上述查詢排序條件改為 order by c1 desc, c2 desc,這種情況下,5.7 的執行計劃要明顯好于 8.0 的,如下:
# MySQL 5.7
mysql explain select * from t1 order by c1 desc , c2 desc limit 5;
+—-+————-+——-+————+——-+—————+———–+———+——+——+———-+————-+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——-+—————+———–+———+——+——+———-+————-+
| 1 | SIMPLE | t1 | NULL | index | NULL | idx_c1_c2 | 10 | NULL | 5 | 100.00 | Using index |
+—-+————-+——-+————+——-+—————+———–+———+——+——+———-+————-+
1 row in set, 1 warning (0.01 sec)
# MySQL 8.0
mysql explain select * from t1 order by c1 desc , c2 desc limit 5;
+—-+————-+——-+————+——-+—————+———–+———+——+——–+———-+—————————–+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——-+—————+———–+———+——+——–+———-+—————————–+
| 1 | SIMPLE | t1 | NULL | index | NULL | idx_c1_c2 | 10 | NULL | 100429 | 100.00 | Using index; Using filesort |
+—-+————-+——-+————+——-+—————+———–+———+——+——–+———-+—————————–+
1 row in set, 1 warning (0.01 sec)
7. group by 不再隱式排序
mysql 8.0 對于 group by 字段不再隱式排序,如需要排序,必須顯式加上 order by 子句。
#
表結構
mysql show create table tb1\G
*************************** 1. row ***************************
Table: tb1
Create Table: CREATE TABLE `tb1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`group_own` int(11) DEFAULT 0 ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC
1 row in set (0.00 sec)
#
表數據
mysql select * from tb1;
+—-+——+———–+
| id | name | group_own |
+—-+——+———–+
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 5 | 5 | 5 |
| 8 | 8 | 1 |
| 10 | 10 | 5 |
+—-+——+———–+
7 rows in set (0.00 sec)
# MySQL 5.7
mysql select count(id), group_own from tb1 group by group_own;
+———–+———–+
| count(id) | group_own |
+———–+———–+
| 4 | 0 |
| 1 | 1 |
| 2 | 5 |
+———–+———–+
3 rows in set (0.00 sec)
# MySQL 8.0.11
mysql select count(id), group_own from tb1 group by group_own;
+———–+———–+
| count(id) | group_own |
+———–+———–+
| 4 | 0 |
| 2 | 5 |
| 1 | 1 |
+———–+———–+
3 rows in set (0.00 sec)
# MySQL 8.0.11 顯式地加上 order by 進行排序
mysql select count(id), group_own from tb1 group by group_own order by group_own;
+———–+———–+
| count(id) | group_own |
+———–+———–+
| 4 | 0 |
| 1 | 1 |
| 2 | 5 |
+———–+———–+
3 rows in set (0.00 sec)
8. JSON 特性增強
MySQL 8 大幅改進了對 JSON 的支持,添加了基于路徑查詢參數從 JSON 字段中抽取數據的 JSON_EXTRACT() 函數,以及用于將數據分別組合到 JSON 數組和對象中的 JSON_ARRAYAGG() 和 JSON_OBJECTAGG() 聚合函數。
在主從復制中,新增參數 binlog_row_value_options,控制 JSON 數據的傳輸方式,允許對于 Json 類型部分修改,在 binlog 中只記錄修改的部分,減少 json 大數據在只有少量修改的情況下,對資源的占用。
9. redo undo 日志加密
增加以下兩個參數,用于控制 redo、undo 日志的加密。innodb_undo_log_encryptinnodb_undo_log_encrypt
10. innodb select for update 跳過鎖等待
select … for update,select … for share(8.0 新增語法) 添加 NOWAIT、SKIP LOCKED 語法,跳過鎖等待,或者跳過鎖定。在 5.7 及之前的版本,select…for update,如果獲取不到鎖,會一直等待,直到 innodb_lock_wait_timeout 超時。
在 8.0 版本,通過添加 nowait,skip locked 語法,能夠立即返回。如果查詢的行已經加鎖,那么 nowait 會立即報錯返回,而 skip locked 也會立即返回,只是返回的結果中不包含被鎖定的行。
# session1:
mysql begin;
mysql select * from t1 where c1 = 2 for update;
+——+——-+
| c1 | c2 |
+——+——-+
| 2 | 60530 |
| 2 | 24678 |
+——+——-+
2 rows in set (0.00 sec)
# session2:
mysql select * from t1 where c1 = 2 for update nowait;
ERROR 3572 (HY000): Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set.
mysql select * from t1 where c1 = 2 for update skip locked;
Empty set (0.00 sec)
11. 增加 SET_VAR 語法
在 sql 語法中增加 SET_VAR 語法,動態調整部分參數,有利于提升語句性能。
· select /*+ SET_VAR(sort_buffer_size = 16M) */ id from test order id ;
· insert /*+ SET_VAR(foreign_key_checks=OFF) */ into test(name) values(1);
12. 支持不可見索引
使用 INVISIBLE 關鍵字在創建表或者進行表變更中設置索引是否可見。索引不可見只是在查詢時優化器不使用該索引,即使使用 force index,優化器也不會使用該索引,同時優化器也不會報索引不存在的錯誤,因為索引仍然真實存在,在必要時,也可以快速的恢復成可見。
#
創建不可見索引
create table t2(c1 int,c2 int,index idx_c1_c2(c1,c2 desc) invisible );
#
索引可見
alter table t2 alter index idx_c1_c2 visible;
#
索引不可見
alter table t2 alter index idx_c1_c2 invisible;
13. 支持直方圖
優化器會利用 column_statistics 的數據,判斷字段的值的分布,得到更準確的執行計劃。
可以使用 ANALYZE TABLE table_name [UPDATE HISTOGRAM on col_name with N BUCKETS |DROP HISTOGRAM ON clo_name] 來收集或者刪除直方圖信息。
直方圖統計了表中某些字段的數據分布情況,為優化選擇高效的執行計劃提供參考,直方圖與索引有著本質的區別,維護一個索引有代價。每一次的 insert、update、delete 都會需要更新索引,會對性能有一定的影響。而直方圖一次創建永不更新,除非明確去更新它。所以不會影響 insert、update、delete 的性能。
#
添加 / 更新直方圖
mysql analyze table t1 update histogram on c1, c2 with 32 buckets;
+——–+———–+———-+———————————————–+
| Table | Op | Msg_type | Msg_text |
+——–+———–+———-+———————————————–+
| db.t1 | histogram | status | Histogram statistics created for column c1 . |
| db.t1 | histogram | status | Histogram statistics created for column c2 . |
+——–+———–+———-+———————————————–+
2 rows in set (2.57 sec)
#
刪除直方圖
mysql analyze table t1 drop histogram on c1, c2;
+——–+———–+———-+———————————————–+
| Table | Op | Msg_type | Msg_text |
+——–+———–+———-+———————————————–+
| db.t1 | histogram | status | Histogram statistics removed for column c1 . |
| db.t1 | histogram | status | Histogram statistics removed for column c2 . |
+——–+———–+———-+———————————————–+
2 rows in set (0.13 sec)
14. 新增 innodb_dedicated_server 參數
能夠讓 InnoDB 根據服務器上檢測到的內存大小自動配置 innodb_buffer_pool_size,innodb_log_file_size,innodb_flush_method 三個參數。
15. 日志分類更詳細
在錯誤信息中添加了錯誤信息編號 [MY-010311] 和錯誤所屬子系統[Server]
# MySQL 5.7
2019-06-08T09:07:20.114585+08:00 0 [Warning] proxies_priv entry @ root@localhost ignored in –skip-name-resolve mode.
2019-06-08T09:07:20.117848+08:00 0 [Warning] tables_priv entry user mysql.session@localhost ignored in –skip-name-resolve mode.
2019-06-08T09:07:20.117868+08:00 0 [Warning] tables_priv entry sys_config mysql.sys@localhost ignored in –skip-name-resolve mode.
# MySQL 8.0
2019-06-21T17:53:13.040295+08:00 28 [Warning] [MY-010311] [Server] proxies_priv entry @ root@localhost ignored in –skip-name-resolve mode.
2019-06-21T17:53:13.040520+08:00 28 [Warning] [MY-010330] [Server] tables_priv entry user mysql.session@localhost ignored in –skip-name-resolve mode.
2019-06-21T17:53:13.040542+08:00 28 [Warning] [MY-010330] [Server] tables_priv entry sys_config mysql.sys@localhost ignored in –skip-name-resolve mode.
16. undo 空間自動回收
· innodb_undo_log_truncate 參數在 8.0.2 版本默認值由 OFF 變為 ON,默認開啟 undo 日志表空間自動回收。
· innodb_undo_tablespaces 參數在 8.0.2 版本默認為 2,當一個 undo 表空間被回收時,還有另外一個提供正常服務。
· innodb_max_undo_log_size 參數定義了 undo 表空間回收的最大值,當 undo 表空間超過這個值,該表空間被標記為可回收。
17. 增加資源組
MySQL 8.0 新增了一個資源組功能,用于調控線程優先級以及綁定 CPU 核。MySQL 用戶需要有 RESOURCE_GROUP_ADMIN 權限才能創建、修改、刪除資源組。在 Linux 環境下,MySQL 進程需要有 CAP_SYS_NICE 權限才能使用資源組完整功能。
[root@localhost~]# sudo setcap cap_sys_nice+ep /usr/local/mysql8.0/bin/mysqld
[root@localhost~]# getcap /usr/local/mysql8.0/bin/mysqld
/usr/local/mysql8.0/bin/mysqld = cap_sys_nice+ep
默認提供兩個資源組,分別是 USR_default,SYS_default
創建資源組:create resource group test_resouce_group type=USER vcpu=0,1 thread_priority=5; 將當前線程加入資源組:SET RESOURCE GROUP test_resouce_group; 將某個線程加入資源組:SET RESOURCE GROUP test_resouce_group FOR thread_id; 查看資源組里有哪些線程:select * from Performance_Schema.threads where RESOURCE_GROUP= test_resouce_group 修改資源組:alter resource group test_resouce_group vcpu = 2,3 THREAD_PRIORITY = 8; 刪除資源組:drop resource group test_resouce_group;
#
創建資源組
mysql create resource group test_resouce_group type=USER vcpu=0,1 thread_priority=5;
Query OK, 0 rows affected (0.03 sec)
mysql select * from RESOURCE_GROUPS;
+———————+———————+————————+———-+—————–+
| RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS | THREAD_PRIORITY |
+———————+———————+————————+———-+—————–+
| USR_default | USER | 1 | 0-3 | 0 |
| SYS_default | SYSTEM | 1 | 0-3 | 0 |
| test_resouce_group | USER | 1 | 0-1 | 5 |
+———————+———————+————————+———-+—————–+
3 rows in set (0.00 sec)
#
把線程 id 為 60 的線程加入到資源組 test_resouce_group 中,線程 id 可通過 Performance_Schema.threads 獲取
mysql SET RESOURCE GROUP test_resouce_group FOR 60;
Query OK, 0 rows affected (0.00 sec)
#
資源組里有線程時,刪除資源組報錯
mysql drop resource group test_resouce_group;
ERROR 3656 (HY000): Resource group test_resouce_group is busy.
#
修改資源組
mysql alter resource group test_resouce_group vcpu = 2,3 THREAD_PRIORITY = 8;
Query OK, 0 rows affected (0.10 sec)
mysql select * from RESOURCE_GROUPS;
+———————+———————+————————+———-+—————–+
| RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS | THREAD_PRIORITY |
+———————+———————+————————+———-+—————–+
| USR_default | USER | 1 | 0-3 | 0 |
| SYS_default | SYSTEM | 1 | 0-3 | 0 |
| test_resouce_group | USER | 1 | 2-3 | 8 |
+———————+———————+————————+———-+—————–+
3 rows in set (0.00 sec)
#
把資源組里的線程移出到默認資源組 USR_default
mysql SET RESOURCE GROUP USR_default FOR 60;
Query OK, 0 rows affected (0.00 sec)
#
刪除資源組
mysql drop resource group test_resouce_group;
Query OK, 0 rows affected (0.04 sec)
18. 增加角色管理
角色可以認為是一些權限的集合,為用戶賦予統一的角色,權限的修改直接通過角色來進行,無需為每個用戶單獨授權。
#
創建角色
mysql create role role_test;
Query OK, 0 rows affected (0.03 sec)
#
給角色授予權限
mysql grant select on db.* to role_test
Query OK, 0 rows affected (0.10 sec)
#
創建用戶
mysql create user read_user @ % identified by 123456
Query OK, 0 rows affected (0.09 sec)
#
給用戶賦予角色
mysql grant role_test to read_user @ %
Query OK, 0 rows affected (0.02 sec)
#
給角色 role_test 增加 insert 權限
mysql grant insert on db.* to role_test
Query OK, 0 rows affected (0.08 sec)
#
給角色 role_test 刪除 insert 權限
mysql revoke insert on db.* from role_test
Query OK, 0 rows affected (0.10 sec)
#
查看默認角色信息
mysql select * from mysql.default_roles;
+——+———–+——————-+——————-+
| HOST | USER | DEFAULT_ROLE_HOST | DEFAULT_ROLE_USER |
+——+———–+——————-+——————-+
| % | read_user | % | role_test |
+——+———–+——————-+——————-+
1 row in set (0.00 sec)
#
查看角色與用戶關系
mysql select * from mysql.role_edges;
+———–+———–+———+———–+——————-+
| FROM_HOST | FROM_USER | TO_HOST | TO_USER | WITH_ADMIN_OPTION |
+———–+———–+———+———–+——————-+
| % | role_test | % | read_user | N |
+———–+———–+———+———–+——————-+
1 row in set (0.00 sec)
#
刪除角色
mysql drop role role_test;
Query OK, 0 rows affected (0.06 sec)
到此,相信大家對“MySQL8.0 新特性是什么”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!