Mysql8.0新特性01
1.前言
Mysql8.0自從2016年就開始迭代了,不管從Mysql8.0.0到Mysql8.0.5都不是GA版本,直到Mysql8.0.11(這裡直接是從Mysql8.0.5調到Mysl8.0.11)才開始釋出GA版本(穩定版),首先說明一點,Mysql8.0版本在官方介紹中它是一個里程碑式的一個版本,它是直接從Mysql5.7版本跳到Mysql8.0的,因此未來Mysql資料庫當屬於Mysql8.0版本的天下了。
2.新版本的一些新的特性
首先說明一下,由於本人真正接觸Mysql比較晚(Mysql8.0都8.0.20了),因此,這裡我就沒有對Mysql8.0新版本進行追蹤,因此這裡就借用別人的文章,開啟地記錄一下Mysql8.0版本到底有了那些新的變化。
3.新特性(部分)
3.1 預設字符集有Latin1變為utf8mb4
在8.0版本之前,預設字符集為latin1,utf8指向的utfmb3,8.0版本預設字符集為utf8mb4,utf預設指向的也是utf8mb4
3.2 MyISM系統表全部都換成了innodb表
系統表全部換成事務型的innodb表,預設的MySQL例項將不包含任何MyISAM表,除非手動建立MyISAM表
# MySQL 5.7 mysql>select distinct(ENGINE) from information_schema.tables; +--------------------+|ENGINE | +--------------------+ |MEMORY | |InnoDB | |MyISAM | |CSV | |PERFORMANCE_SCHEMA| |NULL | +--------------------+ 6rows inset (0.00sec)
# MySQL 8.0 mysql>select distinct(ENGINE) from information_schema.tables; +--------------------+ |ENGINE | +--------------------+ |NULL | |InnoDB ||CSV | |PERFORMANCE_SCHEMA| +--------------------+ 4rows inset (0.00se
3.3 自增變數持久化
在8.0之前的版本,自增主鍵AUTO_INCREMENT的值如果大於max(primary key)+1,在MySQL重啟後,會重置AUTO_INCREMENT=max(primary key)+1,這種現象在某些情況下會導致業務主鍵衝突或者其他難以發現的問題。自增主鍵重啟重置的問題很早就被發現(https://bugs.mysql.com/bug.php?id=199),一直到8.0才被解決,8.0版本將會對AUTO_INCREMENT值進行持久化,MySQL重啟後,該值將不會改變
3.4 DDL原子化
InnoDB表的DDL支援事務完整性,要麼成功要麼回滾,將DDL操作回滾日誌寫入到data dictionary 資料字典表mysql.innodb_ddl_log 中用於回滾操作,該表是隱藏的表,通過show tables無法看到。通過設定引數
3.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" } } } }
3.6 新增降序索引
3.7group by不再隱式排序
mysql 8.0 對於group by 欄位不再隱式排序,如需要排序,必須顯式加上order by 子句
# 表結構 mysql>show create table tb1\G ***************************1.row *************************** Table: tb1 CreateTable: CREATETABLE`tb1` ( `id` int(11) NOTNULLAUTO_INCREMENT, `name` varchar(50) DEFAULTNULL, `group_own` int(11) DEFAULT'0', PRIMARYKEY(`id`) ) ENGINE=InnoDBAUTO_INCREMENT=11DEFAULTCHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ciROW_FORMAT=DYNAMIC 1row inset (0.00sec) # 表資料 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| +----+------+-----------+ 7rows inset (0.00sec) # 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| +-----------+-----------+ 3rows inset (0.00sec) # 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| +-----------+-----------+ 3rows inset (0.00sec) # 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| +-----------+-----------+ 3rows inset (0.00sec)
3.8 JSON特性增強
MySQL 8 大幅改進了對JSON 的支援,添加了基於路徑查詢引數從JSON欄位中抽取資料的JSON_EXTRACT() 函式,以及用於將資料分別組到 JSON 陣列和物件中的JSON_ARRAYAGG() 和JSON_OBJECTAGG() 聚合函式。
在主從複製中,新增引數 binlog_row_value_options,控制JSON資料的傳輸方式,允許對於Json型別部分修改,在binlog中只記錄修改的部分,減少json大資料在只有少量修改的情況下,對資源的佔用。
3.9redo & undo日誌加密
增加以下兩個引數,用於控制redo、undo日誌的加密。
innodb_undo_log_encrypt
innodb_undo_log_encrypt
3.10innodb 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也會立即返回,只是返回的結果中不包含被鎖定的行。
3.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);
3.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;
3.13undo空間自動回收
· 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表空間超過這個值,該表空間被標記為可回收。
3.14增加角色管理
角色可以認為是一些許可權的集合,為使用者賦予統一的角色,許可權的修改直接通過角色來進行,無需為每個使用者單獨授權。
# 建立角色 mysql>create role role_test; QueryOK, 0rows affected (0.03sec) # 給角色授予許可權 mysql>grant select on db.*to 'role_test'; QueryOK, 0rows affected (0.10sec) # 建立使用者 mysql>create user 'read_user'@'%'identified by '123456'; QueryOK, 0rows affected (0.09sec) # 給使用者賦予角色 mysql>grant 'role_test'to 'read_user'@'%'; QueryOK, 0rows affected (0.02sec) # 給角色role_test增加insert許可權 mysql>grant insert on db.*to 'role_test'; QueryOK, 0rows affected (0.08sec) # 給角色role_test刪除insert許可權 mysql>revoke insert on db.*from 'role_test'; QueryOK, 0rows affected (0.10sec) # 檢視預設角色資訊 mysql>select *from mysql.default_roles; +------+-----------+-------------------+-------------------+ |HOST|USER |DEFAULT_ROLE_HOST|DEFAULT_ROLE_USER| +------+-----------+-------------------+-------------------+ |% |read_user |% |role_test | +------+-----------+-------------------+-------------------+ 1row inset (0.00sec) # 檢視角色與使用者關係 mysql>select *from mysql.role_edges; +-----------+-----------+---------+-----------+-------------------+ |FROM_HOST|FROM_USER|TO_HOST|TO_USER |WITH_ADMIN_OPTION| +-----------+-----------+---------+-----------+-------------------+ |% |role_test |% |read_user |N | +-----------+-----------+---------+-----------+-------------------+ 1row inset (0.00sec) # 刪除角色 mysql>drop role role_test; QueryOK, 0rows affected (0.06sec)