赶紧看一下mysql8.0版本的新特性,你的数据库是不是该升级了
這里寫目錄標題
- 前言
- mysql8.0的新特性
- 1、賬戶安全
- 2、優化器索引
- 2.1、隱藏索引(invisible)
- 2.2、降序索引
- 2.3、函數索引
- 3、SQL語句增強
- 4、新增數據分析函數
- 5、InnoDB增強
- 5.1、優化了一些元數據文件
- 5.2、將系統表mysql和數據字典表,全部改為InnoDB引擎
- 5.3、提高了對數據字典表的訪問性能
- 5.4、DDL操作可以是原子性的了
- 5.5、自增列持久化
- 5.6、自增列自動感知最大值
- 5.7、死鎖檢查
- 5.8、鎖定語句新增選項(只針對行鎖)
- 5.9、支持部分快速DDL
- 5.10、InnoDB臨時表空間優化
- 5.11、新增靜態變量:innodb_dedicated_server
- 5.12、其他
- 6、JSON相關
- 6.1、新增內聯路徑操作符
- 6.2、新增json函數
前言
想必現在很多人還在用著mysql5.7或者更早的版本,包括我現在所在公司,也是用著5.7版本,畢竟穩定。
其實mysql8.0.1在2016年就發版了,但一直到2018年發版的8.0.11,才算真正意義上的正式版。
從mysql5到mysql8,其實中間還有mysql6過渡版本和mysql7集群版本,但對于我們而言,可以直接理解為mysql從5.7升級到mysql8.0.11,現在官網最新的版本已經到了mysql8.0.18。
mysql下載官網
mysql8.0的新特性
1、賬戶安全
1.1、用戶創建和用戶授權,分開執行了
5.7版本,可以通過grant一個語句創建用戶并授權
8.0版本,不能使用grant語句創建用戶并授權了,需要先create語句創建用戶,再grant授權
這樣做應該就是為了讓語句更加清晰,各司其職。
1.2、身份認證插件更新
通過語句查看身份認證插件:show variables like ‘default_authentication%’
5.7版本,默認的身份認證插件是:mysql_native_password
8.0版本,默認的身份認證插件改成了:caching_sha2_password
新版本的插件,說是對插件進行了安全和性能方面的升級。
我們在用客戶端連接新版本的mysql的時候,如果沒有升級客戶端,可能會報錯,連接認證失敗。
當然,新版本的認證插件,也可以改回去,可以在mysql的配置文件中改,然后重啟。
(/etc/my.cnf中,搜索mysql_native_password,去調該行注釋即可)
也可以動態修改某個用戶的身份認證插件:
alter user ‘用戶名’@’%’ identified with mysql_native_password by ‘新密碼’
修改后可以通過下面語句查看,單個用戶的身份認證插件被修改了:
select user,host,plugin from mysql.user;
1.3、密碼管理策略加強了
新增限制功能:不允許重復使用以前的密碼,具體變量含義如下:
不能與前3次的密碼重復:password_history=3; (默認0)
不能與30天內的密碼重復:password_reuse_interval=30; (默認0)
修改密碼時需要提供當前用戶密碼(root用戶不受這個參數限制):password_require_current=ON; (默認OFF)
查看變量:show variables like ‘password%’;
1.3.1、修改這些變量,可以直接修改mysql的配置文件,直接在文件末尾追加password_history=3就好了,這樣改是全局所有用戶都修改,而且需要重啟服務
1.3.2、修改這些變量,也可以動態修改變量:set persist password_history=3;
set persist 也是mysql8.0的新功能,設置的變量是持久化的,重啟也會生效。
這個就比之前版本的set global …這種重啟丟失靠譜多了。
其實set persist 的原理就是在目錄(/var/lib/mysql)下新生成了一個文件mysqld-auto.cnf的配置文件,達到持久化的目的,在這個文件中用json的格式把設置的變量保存了,下次重啟mysql,除了讀取本身的配置文件,也會讀這個。
1.3.3、修改這些變量,也可以修改用戶級別:alter uesr ‘用戶名’@’%’ password history 5;
這個策略的原理,其實就是新增了一張歷史密碼記錄表mysql.password_history,每次密碼的修改都會在這個表里記錄起來。
1.4、新功能:角色管理
這個角色的概念,就和RBAC思想中的角色概念一樣,就是為了解決用戶對應很多權限時管理混亂的問題。
使用步驟如下:
定義角色:create role ‘角色名稱’;
角色綁定權限:grant insert,update,delete on 數據庫.* to ‘角色名稱’;
用戶綁定角色(綁定完需要開啟才能生效):grant ‘角色名稱’ to ‘用戶名稱’;
給某個用戶開啟默認角色:set default role ‘角色名稱’ to ‘用戶名稱’;
給某個用戶開啟所有角色:set default role all to ‘用戶名稱’;
也可以用戶登錄,啟用角色:set role ‘角色名稱’;
最后查詢驗證用戶的權限:show grants for ‘角色名稱’;
也可以查詢該用戶的角色擁有的具體權限:show grants for ‘用戶名稱’ using ‘角色名稱’;
撤銷角色的權限:revoke insert,update on 數據庫.* from ‘角色名稱’;
撤銷角色的權限后,相應角色對應的用戶也就沒有該權限了。
其實創建的那個角色,是存在了mysql.user表中的,也就是說mysql還是任務這個角色也是個用戶,只不過沒有密碼。
用戶屬于哪個角色,在mysql.default_role表中。
角色授予了哪些用戶,在mysql.role_edges表中。
2、優化器索引
2.1、隱藏索引(invisible)
也叫不可見索引
8.0開始支持,隱藏索引不會被優化器使用,但數據修改時仍然需要后臺維護。
可以通過看sql查詢的執行計劃(explain sql)看到效果。
將索引設置為可見:alter table 表名 alter index 索引名 visible;
將索引設置為不可見:alter table 表名 alter index 索引名 invisible;
主鍵不可以設置為不可見。
應用場景:軟刪除索引,灰度發布
如果生產環境中,需要刪除索引,但害怕刪除錯了還需要新建這個索引,那就可以先將這個索引設置為隱藏索引,當上線完確認該索引的刪除沒有任何影響時,可以再次真正刪除這個索引。
生產環境中,如果我們要新增一個索引,可以先設置成隱藏索引,然后灰度發布,這時隱藏索引是不可用的,但我們需要維護他。此時可以通過修改一個變量,從而讓當前會話的優化器發現這個索引,從而看到效果,但不會影響到其他會話,相關步驟如下:
執行select @@optimezer_switch\G
看到里面有個開關變量:use_invisible_indexes=off
當前會話級別打開這個開關:set session optimezer_switch=“use_invisible_indexes=on”;
2.2、降序索引
8.0之前的版本,創建索引時可以指定是降序索引還是升序索引,但最終是都創建了升序索引。
8.0開始支持真正的降序索引,但只支持InnoDB引擎的BTREE支持降序索引。
實現真正的降序索引,帶來的好處是:
之前版本,如果查詢時指定索引字段a是升序排序,索引字段b是降序排序,那么其實在看執行計劃的時候可以發現,真正執行時不僅用了索引,還會用到其他的文件排序。
但8.0之后,有了真正的降序索引后,這種情況就只用索引就解決了。
8.0之前版本,對于group by語句有一個隱式的排序。
8.0開始,由于有了降序索引,對于group by語句不在進行隱式排序了,因為之前版本都是默認升序,新版本既有升序又有降序,就不能默認給group by指定了,如果還有排序,必須使用order by了。
2.3、函數索引
8.0.13版本開始支持函數索引了。
這個索引同時也支持降序索引,也支持JSON數據的節點的索引。
這個函數索引,是基于虛擬列功能實現的。
就是相當于給創建函數索引的這個字段,新增加了一列,值是對應字段通過函數運算后的結果,這樣就很好理解了吧,其實我們之前的版本,也有類似的解決方案,就是新增一列,每次新增的時候,這一列存放的總是某列通過函數運算的結果,最后就可以根據這列來查詢了:
alert table 表名 add column 新列名 類型 generated always as (函數(原始列名));
這個sql就是讓新列名總是等于原始列名數值運算函數的結果。
8.0.13只不過是對上面這種方案進行了包裝,不用這樣新增一列并指定了,直接可以創建一個原始列的函數索引,達到相同的目的,讓人看起來更簡潔而已。
創建普通索引:create index 索引名字 on 表名(字段名)
創建函數索引:create index 索引名字 on 表名(函數名(字段名))
函數就是一些方法,比如upper就是將字段轉成大寫。
使用場景:
表中字段是商品名字product,它的值有大寫,也有小寫。
當我們在匹配查詢的時候,如果沒有創建函數索引,那查詢where upper(product)=‘ABCD’時,必然是全表掃描。
如果我們事先針對這個字段創建了upper索引,那查詢的時候就能用上這個索引了。
JSON數據,創建索引時可以指定給JSON中的哪個字段創建索引。目前個人感覺這個功能,有點雞肋。因為一般我們在設計表結構的時候,就是避免存json這種類型的數據的,即使存了,那肯定是類似于文本的數據,更不會根據里面的某個值進行查詢了。所以這個功能,可以忽略吧,只能作為一個慢查詢補救的優化方案。
3、SQL語句增強
8.0開始支持WITH子句:with XX as ABC select * from XX,XX相當于別名
其實就相當于可以用WITH關鍵字定義一個或多個變量,不同的變量都可以指定一個表,前面定義的變量,可以被后面的變量使用,然后后面查詢的時候可以用這些個變量指定的表。
還有一種遞歸的WITH寫法,其實就相當于java中的for循環語句(int i=1;i<100;i++),
所以其實就是sql中可以寫遞歸了,簡單舉例:
上面這個sql,最終返回的是一個列表[1,2,3…100]。
自定義別名(i)中的i就是循環變量,where i<100就是最終結束的條件
每次i+1,都會判斷是否<100,如果滿足條件,則相當于查出一個i的值,直到不滿足條件,最終把所有的值集合輸出。
對于這個sql增強,我目前沒有看出特別合適用它的場景,因為目前的開發模式,對于數據庫來說,只需要提供簡單的增刪改查和事務即可,其他功能相對用的少點,所以我斷定,這個功能目前來沒啥意思。
4、新增數據分析函數
新增關鍵字OVER,用法:
OVER(partition by 字段名 order by 字段名 自定義 ) partition by用于分組,和我們常用的的group by一個意思 order by,這個直接連名字都不改了,就是對分完組的每個組內的數據排序 最后這個自定義,也是作用于分完組的每個組內,可以更詳細的對組內的數據進行篩選,比如可以指定組內從第一個到當前,每次都可以取出從第一個到當前行的總和,等等功能。并新增了一些函數方法(比如排名函數等),同時之前的像SUM等也可以當成這個分析函數。
其實就是對group by的一些聚合函數做了變種,group by是有幾組就是幾條結果,這個新增的分析函數是原數據有幾條,就展示幾條,并沒有聚合。
總體而言,這個也沒啥根本上的改進,還是在原來的基礎上增強,而且貌似增加了復雜性,平均學習成本稍高,或許對部分報表業務,用這個會比較合適,但對于大部分人,估計沒多少人會用這個。
5、InnoDB增強
5.1、優化了一些元數據文件
在/var/lib/mysql/某個數據庫下,刪掉了很多基于文件的數據信息,比如.frm文件,.MYD文件,.MYI文件,其實是將這些文件信息,存在了一個叫 庫名.ibd 的文件下了
5.2、將系統表mysql和數據字典表,全部改為InnoDB引擎
5.3、提高了對數據字典表的訪問性能
5.4、DDL操作可以是原子性的了
比如DDL修改兩個字段,第一個成功,第二個失敗,那最終結果是都失敗。8.0版本之前,這種情況第一個仍然成功,第二個失敗,這就是差別。
5.5、自增列持久化
8.0版本之前,自增列計數器是保存在內存中的,服務重啟后,需要重新讀取自增列最大值,然后生成最新的自增列最大聲,這樣做特殊情況下可能會重復,這還是一個8.0版本前長久的bug。
簡答說下老版本這個bug: 比如自增列是id,已有id自增到10,某個時刻刪除這個10的數據,然后重啟,然后再新增一條數據 如果不重啟,新增的數據的自增id,應該是11 但如果重啟后,新增的數據的自增id,就還是10,因為重啟后,系統掃描這個表,會發現最大id是9,然后新增的話自然就是10了 這其實是我們不愿意看到的情況,因為id為10的這條記錄,雖然被刪了,但如果新增數據,我們還是希望id是11,而不是108.0版本,是把自增列計數器在每次變化的時候,寫入redo log中,這個持久化操作其實是說解決了自增列可能會重復的bug
5.6、自增列自動感知最大值
老版本的自增列,比如自增到10了,如果這時手動把之前id為1的數據的id改為11,那么再次新增,會報錯,因為新增的這條數據,自增計數器給分配的id是11,但其實數據庫中已經有11了。
新版本,針對這個做了優化,不會報錯了,而且會感知到id變為11的操作,然后新增會接著從12開始。
5.7、死鎖檢查
8.0新增加了一個動態變量(innodb_deadlock_detect),用于控制系統是否執行InnoDB的死鎖檢查,默認打開。
開了這個死鎖檢查后,如果出現兩個事物死鎖,系統會立刻讓一個事物失敗。
死鎖檢查,會對性能有較為明顯的影響,為了提高性能,可以將這個功能關閉。
老版本,針對這種死鎖的情況,其實是有一個超時時間的,超過這個時間,也會讓一個事物失效。這個超時時間由一個變量控制(innodb_lock_wait_timeout),好像默認是50秒,我猜新版本這個死鎖檢查,會不會就是相當于把這個值給調小到某個值,然后用另一個開關控制一下。
5.8、鎖定語句新增選項(只針對行鎖)
老版本中,有一種sql:
select … for update
這個是如果查的這個語句有改,就等改完再返回。
新版本,針對這種情況作了加強,語句后可以新增 nowait和skip locked 兩種選項選項。
select … for update nowait;
nowait就是不等了,碰到行鎖立刻返回。
select … for update skip locked;
skip locked就是跳過這條正在修改的,只把沒行鎖的返回。
這個功能還有點用,比如類似于查詢火車票余票的場景,如果查詢的同時,發現有些票正在被修改,那就直接返回或者跳過這些票。
5.9、支持部分快速DDL
alert table … algorithm=instant
這樣就可以避免一些數據復制,比以前普通的DDL操作要快很多,線上環境很適合這樣搞。
5.10、InnoDB臨時表空間優化
使用了共享的臨時表空間ibtemp1。
5.11、新增靜態變量:innodb_dedicated_server
如果有一臺服務器,是專門只裝mysql的,那么打開這個參數,系統會自動配置InnoDB內存參數:innodb_buffer_pool_size,innodb_log_file_size等,會盡量占用系統資源,從而提高系統性能
5.12、其他
6、JSON相關
6.1、新增內聯路徑操作符
新增JSON操作符:column->>path
等價于老版本的:JSON_UNQUOTE(column->path)
也等價于老版本的:JSON_UNQUOTE(JSON_EXTRACT(column,path))
column是json存取的字段名,如果json中有個name屬性
path就是$.name
6.2、新增json函數
JSON_ARRAYAGG():用于生成json數組,括號中是一個列名
JSON_OBJECTAGG():用于生成json對象,括號中可以是多個列名,逗號隔開
JSON_PRETTY():美化json輸出格式
JSON_STORAGE_SIZE():可以查看json列所占用的大小,單位字節。
其實這四個個函數5.7.22就增加了
JSON_STORAGE_FREE():可以查看json列釋放出來的大小,單位字節,實際占用的可能比這個大,這個是實際大小。
JSON_MERGE_PATCH():將兩個json對象合并成一個,相同節點取最后一個節點的值
JSON_MERGE_PRESERV():將兩個json對象合并成一個,相同節點都保留
由于上面這個函數的功能,就是老版本的JSON_MERGE()函數的功能,所以新版版廢棄了JSON_MERGE()函數
JSON_TABLE():將json數據轉換為關系表,可以將這個函數的返回結果當做一個普通的表,并且可以使用sql查詢
這個其實和前面第一第二個函數是相反的操作
總結
以上是生活随笔為你收集整理的赶紧看一下mysql8.0版本的新特性,你的数据库是不是该升级了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ThreadLocal不仅要应付面试,更
- 下一篇: [设计模式] ------ 装饰模式