天天看點

MySQL · 特性分析 · MySQL 5.7新特性系列一

mysql 5.7在2015-10-21釋出了ga版本,即5.7.9,目前小版本已經到了5.7.12。5.7新增了許多新的feature和優化,接下來一個系列,我們就一起來嘗嘗鮮。首先這次主要是預覽feature的變化以及相容性問題。後面的系列,會針對重要的feature展開來學習。

mysql.user表中的plugin更改成not null,5.7開始不再支援mysql_old_password的認證插件,推薦全部使用mysql_native_password。從低版本更新到5.7的時候,需要處理兩個相容性問題。

[相容性]

需要先遷移mysql_old_password的使用者,然後進行user表結構的更新:

1. 遷移mysql_old_password使用者

mysql 5.7.2之前的版本,是根據password的hash value來判斷使用的認證插件類型,5.7.2以後的版本,plugin字段為not null,就直接根據plugin來判斷了。新的密碼從password字段中,儲存到新的字段authentication_string中,password字段廢棄處理。

如果user是隐式的mysql_native_password。直接使用sql進行變更:

如果user是隐式的或者顯示的mysql_old_password, 首先通過以下sql進行查詢:

如果存在記錄,就表示還有使用mysql_old_password的user,使用以下sql進行使用者的遷移:

2. user表結構更新

通過mysql_upgrade直接進行更新,步驟如下[5.6->5.7]:

stop mysql 5.6執行個體

替換5.7的mysqld二進制版本

使用5.7啟動執行個體

run mysql_upgrade更新系統表

重新開機mysql 5.7執行個體

使用者可以通過 <code>alter user 'jeffrey'@'localhost' password expire;</code>這樣的語句來使使用者的密碼過期。

并新增加 default_password_lifetime來表示使用者密碼自動過期時間,從5.7.10開始,其預設值從0變更到了360,也就是預設一年過期。

可以通過以下兩種方法禁止過期:

隻需要通過mysql_upgrade更新mysql.user系統表就可以使用密碼過期新功能。

使用者可以通過以下文法進行賬号鎖定,阻止這個使用者進行登入:

如果mysqld編譯使用的openssl,在啟動的時候,預設建立ssl, rsa certificate 和 key 檔案。

但不管是openssl還是yassl,如果沒有設定ssl相關的參數,mysqld都會在data directory裡查找ssl認證檔案,來盡量打開ssl特性。

不存在相容性的問題

5.7開始建議使用者使用 <code>mysqld --initialize</code>來初始化資料庫,放棄之前的mysql_install_db的方式,新的方式隻建立了一個root@localhost的使用者,随機密碼儲存在~/.mysql_secret檔案中,并且賬号是expired,第一次使用必須reset password,并且不再建立test db。

5.7 sql_mode的預設值變更為:

而在5.7之前,sql_mode的預設值都隻有mode_no_engine_substitution。

是以在5.7預設的情況下,比如grant不存在的使用者的時候,會報一下錯誤:

必須先使用create user,然後再使用grant user。

預設sql mode發生變更會導緻sql的行為不一緻。

支援online rename index操作, in_place并且不需要table copy。

變更varchar 類型字段的長度支援inplace方法,但有一個限制,即用于表示varchar字段長度的位元組數不能發生變化,也就是支援比如varchar的長度在255以下變更或者255以上的範圍進行變更,因為從小于255變更到大于255,其size的位元組需要從1個增加到2個。

注意:減少varchar的長度,仍然需要table copy。

因為innodb臨時表的資料不再不受redo保護,而redo隻保護臨時表的中繼資料,是以大幅提升了臨時表的性能。

并且innodb臨時表的中繼資料儲存在一個新的系統表中即innodb_temp_table_info,

臨時表将建立一個統一的表空間,我們稱之為臨時表空間,其目錄位址可以通過參數innodb_temp_data_file_path來設定。系統在啟動的時候,都會建立這個表空間,重新開機會删除重建。

例如:

并且5.7存儲引擎預設都變更成innodb了:

注意: 在開啟gtid的情況下,非auto commit或者顯示begin的context下,create 或者drop 臨時表,仍然和5.6一樣:

另外, insert into t select * from t也會遇到錯誤,不能在一個sql語句中reference兩次臨時表。

備注: 因為innodb臨時表進行了比較大的變動,我們會專門進行一次詳細的介紹。

并且支援在spatial data types上建立index,加速查詢。

buffer pool dump和load支援一個新的參數innodb_buffer_pool_dump_pct,即dump的比例,并且使用innodb_io_capacity 來控制load過程中的io吞吐量。

從5.7.4開始,innodb_page_cleaners參數可以設定,支援多線程flush dirty page,加快髒塊的重新整理。

mysql 一直使用double write buffer來解決一個page寫入的partial write問題,但在linux系統上的fusion-io non-volatile memory (nvm) file system支援原子的寫入。

這樣就可以省略掉double write buffer的使用, 5.7.4以後,如果fusion-io devices支援atomic write,那麼mysql自動把dirty block直接寫入到資料檔案了。這樣減少了一次記憶體copy和io操作。

mysql 5.7之前的版本,innodb并不支援分區表,分區表的支援是在ha_partition引擎上支援的,從5.7開始,innodb支援原生的分區表,并且可以使用傳輸表空間。

mysql_upgrade會掃描ha_partition引擎支援的innodb表,并更新成innodb分區表,5.7.9之後,可以通過指令alter table … upgrade partitioning.進行更新。如果之前的版本大量使用了分區表,要注意使用mysql_upgrade會消耗非常長的時間來更新分區表。

mysql 5.7.5之後,可以online動态調整buffer pool size,通過設定動态的參數innodb_buffer_pool_size來調整,并且根據innodb_buffer_pool_resize_status狀态來檢視resize的進度,因為resize的過程是以chunk為大小,把pages從一個記憶體區域copy到另一片記憶體的。

mysql 5.7.5之前,在recovery的過程中,需要掃描所有的ibd檔案,擷取元資訊, 5.7.5之後,新加了一種redo log類型,即mlog_file_name, 記錄從上一次checkpoint以來,發生過變更的檔案,這樣在recovery的過程中,隻需要打開這些檔案就可以了。

因為增加了新的log record type,需要安全的關閉5.7之前的執行個體,清理掉redo。

支援建立表空間,例如

并可以在建立表的時候,指定屬于哪個表空間,

因為可以任意指定空間目錄,要注意更新過程中,不要漏掉目錄。

支援innodb資料檔案加密,其依賴keyring plugin來進行秘鑰的管理,後面我們單獨來介紹innodb加密的方法,并且rds也實作了一種innodb資料檔案透明加密方法,并通過kms系統來管理秘鑰。例如:

未完待續