MySQL 5.7 新特性詳解

碼頭工人 8年前發布 | 114K 次閱讀 MySQL

我們自豪的宣布 MySQL 5.7 穩定版開放下載了。 MySQL 5.7.9 是目前世界上最流行開源數據庫的一令人興奮的新版本, 比 MySQL 5.6 快 3 倍,同時還提高了可用性,可管理性和安全性。一些重要的增強功能如下: 

  1. 性能和可擴展性:改進 InnoDB 的可擴展性和臨時表的性能,從而實現更快的網絡和大數據加載等操作。

  2. JSON支持:使用 MySQL 的 JSON 功能,你可以結合 NoSQL 的靈活和關系數據庫的強大。

  3. 改進復制 以提高可用性的性能。包括多源復制,多從線程增強,在線 GTIDs,和增強的半同步復制。 

  4. 性能模式 提供更好的視角。我們增加了許多新的監控功能,以減少空間和過載,使用新的 SYS 模式顯著提高易用性。

  5. 安全: 我們貫徹“安全第一”的要求,許多 MySQL 5.7 新功能幫助用戶保證他們數據庫的安全。

  6. 優化: 我們重寫了大部分解析器,優化器和成本模型。這提高了可維護性,可擴展性和性能。

  7. GIS: MySQL 5.7 全新的功能,包括 InnoDB 空間索引,使用 Boost.Geometry,同時提高完整性和標準符合性。 

上述只是一些亮點,我鼓勵你們深入了解。可以通過一系列的里程碑博客5.7.15.7.25.7.35.7.45.7.55.7.65.7.75.7.8 —甚至通過記錄他們的技術規范和實施細則的個人 worklogs ,或許你只是想在 github.com/mysql 上看一下代碼。我們已經實施了 365  個worklogs,添加了 1007 個 MTR 測試,并且修復了 28125.7 個具體的 bug。勢不可擋的感覺,所以這個“小的”指導可能是有用的。

非常感謝開發團隊的每一個成員,是你們成就了這些!我說開發是指所有人,包括:需求,設計,編碼,審核,測試,bug 修復,文檔,發布和實驗支持,真的是一個團隊的努力。非常感謝開源社區的每一個人,感謝你們反饋 bug,建議和貢獻!一個世界的努力。

為 MySQL 添加 JSON 支持

使用 MySQL 的最新的 JSON 功能,你可以結合 NoSQL 的靈活和關系數據庫的力量。

我們開發了一個 JSON 數據類型和一個二進制存儲格式 ,使用服務器可以高效存儲,檢索和查找 JSON 數據(WL#8132) 。

這項工作改進了 CREATE TABLE 和 ALTER TABLE ,所以你可以創建 JSON 類型的數據列,并且它擴展了 Field 類,允許對 JSON 類型數據進行 INSERT和SELECT 操作。

我們已經引入了一系列服務端功能,內置的 JSON 函數(WL#7909),這項工作可以讓用戶,從其他關系數據構建 JSON 數據,從 JSON 數據中抽取關系數據, 感知 JSON 數據值和文本(效度,長度,深度,鍵)的結構,對JSON 數據進行檢索和操作。

我們已經介紹了 JSON 比較器 ,類似于 DATE/TIME/DATETIME(日期/時間/日期時間)比較器,它允許 JSON 常量和 SQL 常量比較、JSON 變量和 SQL 變量比較(WL#8249)。比較器依賴在 WL#7909 添加的 DOM 元素的支持。比較器將 SQL 常量轉換為為 JSON 變量然后比較他們的值。

我們已經實現了 JSON 變量值排序(WL#8539),即一個函數產生內部方法 filesort 所需的用老排序 JSON 值的排序鍵。當排序 JSON 變量時用 ORDER BY,它將會返回 JSON 比較器WL#8249 定義的排序規則所排序的結果。

我們已經為生成的列(WL#8170)實現了一個表達式分析器。這樣做可以讓我們的排序和參考優化器有機會使用已經為生成的列定義的索引。關于這個功能的一個案例是在 JSON 文檔上產生和自動使用索引。

我們已經在 SQL 查詢(WL#8607)中加上了內聯 JSON 路徑表達式。MySQL 現在這樣執行查詢:SELECT … FROM t1 WHERE t1.json_field->”$.path.to[0].key”= 123;

生成的列&可生成索引的虛擬化列

我們第一次實現生成的列(WL#411, WL#8114)。每列的值,不像一個有規律的字段的值,沒有通過用戶設置而是當行創建或者更新時通過服務器使用用戶定義表時定義的特殊的表達式計算。生成的列也可以被物化(被存儲)或者非物化(虛擬)。關于這方面的內容可以看看 Evgeny Potemkin 的文章“在MySQL 5.7.5中的生成列“。

然后我們在非物化虛擬列上為二級索引的創建提供了支持,以及這些索引在快速檢索計算值和搜索方面的使用((WL#8149, WL#8227WL#8481) 。

非物化虛擬列是用來處理在真正的 InnoDB 索引記錄中不存在時,但是他們的元數據在 InnoDB 系統表和元數據緩存中注冊了的情況,虛擬列為表提供了靈活性和保存空間,還有較重要的一點,添加/刪除這樣的列而不用重新構建表。這樣做是存儲和處理非關系型數據如 JSON 最好的選擇。然而,由于這些列不是物化的,因此掃描和檢索比一般的列(物化的列)要慢一些,但是,虛擬列的值在二級索引里物化了,因此這些列的數據還是比較容易進行檢索和處理的。因此這也極大的提高了虛擬列的實際值。通過這樣的方式,在一個虛擬生成的列上創建索引也變成了在線操作.


性能&可伸縮性

從社區反饋,賬戶追蹤和在計算機硬件開發及本身架構方面了解到,  對 MySql 來說性能和可伸縮性是最重要的部分。迄今為止,在 MySql5.7 中, 我們已經在 InnoDB 實現了對只讀(RO)結果的可伸縮性處理和在服務層明顯的提高了連接速度的處理。我們也在 InnoDB 上的可伸縮性讀寫,提高內部操作(快速穩定的刷新/清除),和快速批量數據加載方面有了很好的進展。

InnoDB 的可伸縮性只讀。我們已經提高了只讀和多數讀取工作負載的性能。我們也已經極大的提高InnoDB 處理只讀事務(WL#6047, WL#6899, WL#6906, WL#6578)。我們也去掉了服務層連接與元數據鎖定(MDL) 有關的部分和 InnoDB 中 THR_LOCK 鎖的使用(WL#7304, WL#7305, WL#7306, WL#6671)。在 WL#6671 之后的一些工作負載中,LOCK_grant 鎖就在未來可伸縮性的瓶頸方面清晰了很多; 例如,單張表 InnoDB POINT_SELECT Sysbench 的測試(見 Bug#72829)。目前這個問題已經通過分割 LOCK_grant 鎖解決了(見WL#8355)。最終,我們也在涉及到基于內存的臨時表創建的工作負載方面突破了 LOCK_plugin 和 THR_LOCK_lock 鎖的瓶頸;例如,InnoDB 中像 Sysbench 的 SELECT_DISTINCT 的測試。但是,我們不應該為內部臨時表獲得這些鎖,因此,我們清除了這些不必要的開銷(見WL#8356)。也可以看一下 Dimitri Kravtchuk 的文章“MySQL 性能:  MySQL 5.7 達到 500K QPS ““MySQL 5.7 : 使用 InnoDB 緩存插件超過 1M QPS“,Sunny Bains 的文章“MySQL5.7.3對事務生命周期的改進“,和 Jimmy Yang 的文章”MySQL 5.7.3: 深入了解使用 InnoDB緩存達到 1百萬QPS “

InnoDB 讀寫擴展。改善了數據庫的讀寫負載性能。移除了 InnoDB 的索引死鎖(WL#6363, WL#6326)。現在的索引鎖被替換成更加精細的樹的“塊鎖”,然而以前常常用它來保護整個的索引樹結構。可以參考 Yasufumi Kinoshita 的文章“MySQL-5.7 improves DML oriented workloads(MySQL-5.7 改善了面向數據操作語言的工作負載)”。

InnoDB 更快的并行數據刷新。掃描刷新一批隊列數據的時候,減少了需要檢索的頁面數目,從而提高了頁面更新的速度(WL#7047)。檢索的時間復雜度已經從 O(n*n) 降低到了 O(n)。與此同時,利用多線程的多頁清除技術實現了并行的數據刷新(WL#6642)。這使得數據庫在多核系統上的擴展性和吞吐量均大大得到增強的同時,避免了數據刷新成為瓶頸。最后,改善了自適應的刷新算法以及其他相關機制,來達到更加一致和平滑的吞吐量。

加速連接處理。在某些應用場景下(例如:PHP 應用程序)客戶的連接常常只有很短的生命周期,有時只用執行單次的查詢。這意味著,用在處理連接和斷開連接的時間的長短嚴重關系到整體的應用程序的運行性能。在 5.7 下,壓縮了線程初始化和網絡初始化的負載成為一個普通的線程(WL#6606)。取而代之的是 MySQL 雙倍的處理高頻的連接與斷開連接的能力,從每秒鐘 26K 次的處理能力提升至每秒鐘 56K 次。也可以參考 Jon Olav Hauglid 的一篇文章“Improving connect/disconnect performance“

加載塊數據的性能的提升。為了創建索引所進行的塊數據的加載,(WL#7277)。通過實現塊數據的索引排序,從而加速了 CREATE INDEX 運算操作符的實現。在此之前,InnoDB 循環遍歷基表,為每訪問一次基表里的每條記錄創建一個索引。在此次更新之后,InnoDB 可以一次從基表讀取多條記錄,并且通過索引的鍵值排序這些記錄,從而由單次的塊操作下創建出一整塊記錄的索引集。

在線操作

“時刻在線”的特性對于所有完美的 web 解決方案而言都是必需的。對于數據庫管理員或者網站的開發運維人員來說,在不影響前臺服務的條件下調試和拓展其后臺數據庫系統是極其重要的。因此,我們要確保 MySQL 在這一領域處于領先地位。在 5.7 下,我們提供如下這些:

提供了確保全局事務始終在線是方式(WL#7083)。因此,讀寫的操作在此過程中是可行的,并且服務器不需要同步或者重啟。在此次更新之前,用戶不得不停止所有的更新操作,同步所有的服務器,并且同時重啟服務器。這意味著,為了確保全局事務,必須提前規劃好服務器的宕機時間。可以參考 Sven Sandberg 的文章”Enabling Global Transaction Identifiers Without Downtime in MySQL 5.7.6“(利用 MySQL 5.7.6 在不宕機的情況下確保全局事務)

我們已經添加了動態修改innodb_buffer_pool_size值的功能(WL#6117).。這個功能可以在無當機的情況下修改緩沖池的大小。參見Yasufumi Kinoshita的文章:“Resizing the InnoDB Buffer Pool Online“。

我們已經實現了 UNDO 日志的自動分割,如果 UNDO 分片大小已經配置就可以使用((WL#6965). InnoDB 的操作有多個 UNDO 表空間會定時分割,一次一個。當一個 UNDO 表空間正在被分割時,其他的 UNDO 表空間可以繼續為分割管理服務以將分割過程的影響降到最小。這個功能的目的是為了防止在一些應用場景中發生的 UNDO 日志文件過大問題。參見 Scott Ellsworth 提交的 Bug#1287 。

我們已經增加了在線 ALTER TABLE, RENAME INDEX (WL#6752WL#6555) 操作,擴展了VARCHAR 數據列的操作大小(WL#6554)。

通過新的命令 CHANGE REPLICATION FILTER,我們實現了一個從服務器可設置選項--replicate-*settable (WL#7057)。這些選項可以在服務器運行期間動態修改,使用用戶可以修改復制過濾規則,不要停止或重啟服務。這個工作起源于 Davi Arnaut 的貢獻 (Bug#67362)。參見 Venkatesh Duggirala’s 的文章 “Making MySQL Slave Replication Filters Dynamic“。

我們已經可以在不停止復制的情況下執行 CHANGE MASTER(WL#6120)。使用 CANGE MASTER TO 添加或修改選項,在以前要先先執行 STOP SLAVE 然后執行 CHANGE MASTER TO 命令。這個工作放松了這個限制。參見 Shivji Jha的文章 “Change master without stopping slave altogether“。

優化改進

深入優化區才是最令人興奮的事,就像新的Cost Model,一個新的升級的分析器,一個優化架構分層 , 和一個新的 GIS 實現。另外我們已經實現了下面的功能需求:Query Rewrite Plugins (WL#7589) : 我們已經實現了查詢重寫插件,以及為使用者寫他們自己定制的查詢重寫插件提供了一個框架(API)。查詢重寫插件指定了怎樣確定一個已發送到服務器的查詢應該在他們被服務器執行之前被重寫。一種用法是通過添加一個標記到查詢里去增強/阻止一個確定的查詢計劃。我們的查詢重寫插件是最好的工具 ,特別是處理那些當用戶不能在應用內部重寫查詢時的查詢,例如:由于它是從一個外部工具(如對象關系映射工具 Hibernate)衍生而來的或從一些第三方應用。見 Martin Hansson 的文章“ 寫自己的查詢重寫工具:Part 1” 和“Part 2“。

對 FROM 子句中的子查詢的處理和 view(WL#5275)一樣:我們對派生表和視圖有統一的擴展,目前,FROM 中的子查詢(派生表)已經完全物化,而從相同查詢表達式創建的視圖則有時物化,有時合并到外部查詢。這種做法存在不一致問題,會導致嚴重的性能問題,這項工作解決了 Bug#59203Bug#67631, 和 Bug#1275

讓索引的切換代價最小化(WL#6986):為了支持"ORDER BY ... LIMIT N",我們已經做出決定make_join_select()。這項工作解決了Bug#73837

使用范圍掃描替換“IN queries”使用行值表達式(WL#7019) :我們刪除了以前將 WHERE 條件重寫進等效 AND/OR 形式的前置條件。見 Mark Callaghan 報告的 Bug#31188 和 Domas Mituzas 報告的Bug#16247。和 Martin Hansson 的文章“Range access: now in an IN predicate near you“.

“UNION ALL” 不再創建一個臨時表 (WL#1763) : 如果沒有必要在 5.7 優化器將避免為 UNION ALL 查詢創建臨時表,例如,沒有頂級的 ORDER BY 子句。在執行大的聯合查詢時這將減少磁盤空間和磁盤 I/O when ,有時這是很重要的,終端將會立即獲得第一行。見 Mark Callaghan 報告的Bug#50674 ,還有 Norvald H. Ryeng 的文章 “State of the UNION“。

在排序緩沖中的非存儲字段不受影響N(WL#1509) : 這項優化有助于更好的利用排序緩沖區,從而避免或減少在排序時使用磁盤。用戶的好處是提高查詢性能。

EXPLAIN 的運行查詢(WL#6369) : 如果你在一個 session 里要運行一個耗時的查詢這個功能非常有用;使用EXPLAIN FOR CONNECTION;在另一個 session 上運行可以產生關于對延遲原因有用的信息以幫助你優化你的模式和表達式。

JSON EXPLAIN (WL#6510) : 我們已經通過打印整個查詢消耗,每張表的消耗,和數據處理數量的方式增強了JSON EXPLAIN輸出。這將會讓用戶更容易看出好的執行計劃和壞的執行計劃。見?ystein Gr?vlen的文章“MySQL EXPLAIN 說明“。

條件過濾在優化器中使用(WL#6635)。這項工作提高了連接排序(Cost Model 操作的一部分)。我們通過不僅考慮選擇入口方法的條件,而且也考慮所有其他相關條件的方式獲得了很好的前綴列的估算。  見 J?rgen L?land 的文章“從新的角度看 MySQL 查詢優化” part1 和 part2 。

改進 ONLY_FULL_GROUP_BY SQL 模塊(WL#2489):我們已經改進了 ONLY_FULL_GROUP_BY SQL 的工作模式并且也默認在 5.7.5 以上版本可用。由于服務器目前也意識到了函數依賴,因此這項工作讓SQL模塊遠不如嚴謹的選擇/排序表達式 。 所以這項工作也引起了很多用戶抱怨,例如在 Roland Bouman 的文章“揭穿分組的神話” 和 Bug#51058。見 Guilhem Bichot 的文章“MySQL 5.7: only_full_group_by 改進, 意識到函數依賴, 默認可用!“。

分析器重構

我們以增量方式進入了重構 SQL 分析器階段。由于舊的分析器的復雜語法和自上而下的分析方式而導致缺乏可維護性和可擴展性,因此它已經不能滿足要求。迄今為止我們已經做了很多準備工作(WL#5967, WL#7199),重構 SELECT 聲明 (WL#7200),  SET 聲明 (WL#7203),INSERT/REPLACE  聲明(WL#7201),DELETE  聲明 (WL#7202) 和 UPDATE 聲明 (WL#8062)。我們計劃重寫整個分析器。見 Gleb Shchepa 的文章“MySQL 5.7.4 LAB release 重構解析器“。


優化標記

為了優化標記我們已經增加了分析規則來支持新的標記語法(WL#8016)。目前在一個 SQL 語句內,標記可以在 SELECT|INSERT|REPLACE|UPDATE|DELETE 關鍵詞之后直接指定,但是他們必須放在/*+ */以內。這不僅為最終用戶提供了較為一致的和容易使用的管理標記方法,而且內在的重構也讓它更容易地從前端為服務器端添加額外的標記 (見 WL#8241 和 WL#8243 以下)。我們也實現了通用的功能(WL#8017)對所有的標記提供新的語法(見 WL#8016)。這包括:1.在解析期間連接相關查詢塊和標記的數據結構。2.為解決數據庫對象名稱(例如表名,索引名等等)的功能函數和關聯相關對象的標記。3 .優化器能夠用于在當前查詢內查找標記的一個數據結構。

我們已經添加了新的“索引層標記”,這種索引標記可以讓用戶控制應該成為索引條件下推(ICP),多范圍讀(MMR),和范圍優化的候選索引(WL#8243)。我們也已經增加了一種新的標記,這種新的標記可以替代表的設置,而讓用戶設置優化器在執行查詢期間決定是否使用連接緩存或批量關鍵字存取(WL#8241)。

我們還新增了控制子查詢執行策略的標記(WL#8244)。這包括是否使用半連接,使用哪種半連接策略,如果不使用半連接,那么是使用子查詢實例化還是 in-to-exist 轉變。這項功能使用了由 WL#8016 和 WL#8017 提供的新的語法和基本功能來標記。注意:這項功能可以阻止任何特定的半連接策略,包括不能通過使用--optimizer_switch來關閉的多淘汰策略。

優化器重構

前面提到的分析,優化,和執行的階段都涉及到了這部分內容。幾乎每一個模塊都涉及到不同的部分和優化器部分。因此,維護代碼庫的消耗變得很高而且不易擴展。我們以清晰的分離這些部分為目的而開始優化器重構項目。由于代碼庫的重構,優化器變得非常快。例如,我們明白這是作為提高我們的預處理語句的先決條件。見 WL#6016,  WL#6042,  WL#7082WL#7540,和 WL#7870 和 Guilhem Bichot 的文章“ MySQL5.7:重構預處理語句的內核“。

面向新的消耗模塊

消耗模塊項目的動機和概述在 J?rgen L?land 的文章 “MySQL 優化 Cost Model 項目“里有描述 。在 5.7 上為了“條件過濾”(part1 和 part2)和“準確的 InnoDB 統計”,我們改進的 DBT-3 的性能。另外我們也已經為其他的很多目標奠定了基礎,例如,由于代碼重構,用戶消耗數量變得可控,并且可以了解到數據消耗是在磁盤上還是在緩存上。

我們開始了重構已有的消耗模塊代碼并清除了難以理解的代碼。這是為了讓代碼更加的穩定,并且盡可能多的讓用戶為他們自己的硬件環境配置和調整,這也為存儲引擎提供數據請求消耗因子是在緩存上還是磁盤上,奠定了基礎工作。我們也做了些基礎準備工作,并清除費解的代碼。目前已經替換成,普通用戶通過配置改變消耗值,服務器管理員可以調整消耗值,而不需要改變源代碼。(WL#7182, WL#7209, WL#7338, WL#5869, WL#6068, WL#7339, WL#7276, WL#7315, WL#7316, WL#7168)。

我們已經擴展了消耗模型優化器。這個舊的優化器可以讓存儲引擎估算一張表目前在內存中大約需要多少行和多少索引(WL#7340)。而新的優化器將使用不同的消耗常量來計算獲取在內存中的數據和需要從磁盤中讀取的數據的消耗。在最初的實現里,這兩個消耗常量有相同的默認值,但是可以通過服務器管理員修改讓優化器在內存中緩存的數據和需要從磁盤讀取的數據使用不同的消耗常量。而目前,估算關于數據是否在內存中還是需要從磁盤中讀取僅僅基于探索算法。而當這些估算支持通過獨立于存儲引擎而實現時,這些估算的精度將會有很大的提升。

分頁壓縮

我們已經在 InnoDB 層實現了透明分頁壓縮 (WL#7696)。這個功能可以在任何操作系統/文件系統中組合運行,并支持稀疏文件和“打孔”(例如:fallocate 函數的 FALLOC_FL_PUNCH_HOLE 標示)。這其實很簡單——給一個 16K 的頁面,我們使用你最喜歡的壓縮算法壓縮它,然后輸出壓縮后的數據,接下來我們“打一個空”釋放 16k 塊中沒有使用的部分到文件系統中。


InnoDB 全文檢索

在 5.6 中,我們介紹了 InnoDB 全文搜索。目前,我們添加了更靈活性和更加優化的全文搜索。例如,目前在全文本索引支持外部的分析器,就像 MyISAM (WL#6943)。插件可以替代內置分析器也可以作為一個前端來使用。見來自 Daniel van Eeden 和 Hartmut Holzgraefe 的功能需求(Bug#68816) 。我們也實現了標記優化器,這個優化器可以將查詢傳遞到 InnoDB ,因此 InnoDB 可以跳過全文檢索部分,例如,如果不需要,他們可以不用計算排序值 (WL#7123)。見 Shaohua Wang 的文章“InnoDB 全文索引支持插件分析器”和 Matt Lord 的文章“ 使用 InnoDB 的全文檢索排序“.

我們也在 InnoDB 上實現了支持 CJK(中文,日文,和韓文)的全文檢索 (WL#6607):我們為 CJK 提供了一個默認的全文分析器 (N-GRAM 分析器) 和一個為日文提供支持 MeCab 的備選插件。用戶也可以使用可插拔分析器實現他們自己的支持 CJK 的全文檢索分析器插件。見 Shaohua Wang 的兩篇文章“InnoDB Full-Text : N-gram Parser”和“InnoDB Full-Text: MeCab Parser“。

性能架構

對于我們的用戶和任何數據管理系統來說,監控都是非常重要的。在這方面我們的目標是要做到一流的水平。我們的監控的核心策略包含 MySQL 5.5 引入的 性能架構。這是一個特殊的 MySQL 存儲引擎,用來存儲動態創建的事件,然后以慣用的 SQL 接口提供對事件和對應配置的查詢。5.7 版我們繼續提供對監控的擴展和增強,通過 性能架構 架構,我們可以提供這些對這些信息的監控:Metadata Locking (WL#5879),事務 (WL#5864), 內存使用 (WL#3249WL#7777), Stored Programs(WL#5766), Prepared Statements (WL#5768).

在性能架構里我們還提供了 SHOW SLAVE STATUS 信息(WL#3656) 和 用戶變量(WL#6884) 。我們還提供了全局和會話級別的狀態和變量(WL#6629),同時為了向前兼容繼續支持SHOW STATUS 和 SHOW VARIABLES 命令。另外,還提供了對長時間運行的操作進行統計 (WL#5889) 。

我們已經提高了內存分配的性能架構(WL#5889) 。此前的性能架構當服務啟動時會分配所需的所有內存。現在我們可以根據服務負載自動調整內存消耗,從而降低開銷(WL#7802)。我們通過重構性能架構的內部緩沖減少內存的使用,當數據表過多時,表結構導致的內存過載會有所改善。(WL#7698) .

我們通過允許用戶/主機排除提高易用性(WL#7800) .這了實現這一點,一個名為 ENABLED 列已經添加到表 setup_actors 為用戶提供排除或包含指定規則的能力。 我們已經提供了兩個與查詢文本長度 —SQL text 和 digest—匹配的實體 (WL#7270). 兩者默認大小1024 bytes。

現在我們通過標準接口—PERFORMANCE_SCHEMA.THREADStable,  Audit log API,  Audit log file, 和 General Query Log (WL#7729)暴露連接類型信息。到現在為止 MySQL 沒有為 DBA 提供已經建立和使用的連接可視化;例如區分未加密的 TCP/IP 連接 , 或者 socket,共享內存或者管道連接。 

現在我可以對單個線程打開或關閉歷史記錄 (WL#7795) 。到目前為止,全局自定義標記已經可以用來控制是否記錄歷史事件的日志。這些標記對服務器來說是全局的,因此不同線程的歷史事件的集合有的有,有的沒有。對于這個功能,現在 DBA 可以對會話,賬戶, 用戶, 和主機指定他們想收集的歷史記錄,而獨立于基本的打開或關閉設置。這讓 DBA 更加精確的控制什么樣的事件可以在歷史數據表里記錄日志,從而減少了當歷史數據僅需要基礎會話的子集時的運行負載,也減少了在 Performance  Schema 表中不想要數據——events_waits_history_longevents_stages_history_longevents_statements_history_longevents_transactions_history_long——這些數據有助于在繁忙服務器上促進故障排除(也會產生很多事件)。見 Mayank Prasad 文章“Performance Schema implementation Internals: Registering instruments“, “MySQL Performance Schema : Prepared Statements Instrumentation“, “MySQL Performance Schema: Instrumentation Exceptions“, 和“MySQL Statement Digests“.

SYS 模式

我們已經在 MySQL 服務里默認的整合了 SYS Schema(以前的 ps_helper) (WL#8159)。在過去的一年里 MySQL SYS schema 項目在我們的基礎用戶中廣受歡迎。在我們的基礎用戶中的許多 DBA 和開發者注意到它更加簡單的配置和查詢 Performance Schema,也更加的簡單的整合它和 Information_Schema,還有其他更多功能。例如,看一下這篇文章,也可參考 Mark Leith 的文章“The MySQL SYS Schema in MySQL 5.7.7“。

Fabric支持

 在 2014 年 5 月 27 日,Oracle 宣布了 GA 支持 MySQL Fabric。目前服務器團隊正在為提高切片,故障轉移,和服務器集群管理而改進一些功能。

我們已經為清理會話狀態而實現一個新的服務器方法(WL#6797)。現在用戶可以重置已有連接,例如,清理已有的會話和釋放資源。

我們也增加一個新的服務器方法來實現離線服務器(WL#3836)。這個功能為升級和其他的維護而使用。設置服務器處于離線模式可以優雅的斷開所有連接的用戶除了那些有超級權限的用戶。當系統處于離線模式時,“超級”用戶可以連接和管理系統。

我們增加了一個服務器標記來檢測已經發起的新的事務 (WL#6631)。session_track_transaction_state 是一個新的系統變量。在一個負載平衡的設置里,需要知道在新的事務啟動時,哪一個連接器可以轉換,從而從連接池里使用不同的連接。關鍵就在于檢測當事務“刷新"時并且還沒有對事務做任何讀寫操作。那么僅僅在這種情況下連接器可以轉換使用不同的連接,如果一個聲明啟動一個新的事務并有讀寫操作,那么就不能再轉換連接,除非先做一個 ROLLBACK 操作。

我們來介紹一個基于 DBA/Application 定義標志的同步機制 (WL#6940,WL#8161)。一個有超級權限的用戶可以在服務器設置一個全局的標志(例如一些 ID)并且客戶端可以設置會話標志。在執行查詢之前,會話標志會和全局標志比較,如果這兩個標志不同就會觸發一個錯誤。

默認安全

MySQL 5.7 的目標是成為發布以來最安全的 MySQL 服務器,這就是說在 SSL/TLS 和全面安全開發方面有一些重要的改變。

MySQL 開發現在默認是安全的(WL#6962)。安裝的過程中只創建一個 root 賬號,root@localhost,并隨機自動的為這個賬號生成一個密碼,而且標記這個密碼為過期狀態。然后 MySQL 管理員必須使用 root 和隨機生成的密碼登陸,然后使用 SET PASSWORD 命令設置一個新的密碼。

安裝過程中創建非隨機用戶賬號,默認沒有演示相關文件(WL#6977 WL#6973WL#7787)。測試數據庫和演示相關文件在其他包下。

我們簡化了 mysql 服務器安裝后的初始化過程,也移除了 mysql_install_db 這個玩意(以前安裝過mysql的同學應該清楚這個腳本,可以手動初始化數據庫)(WL#7307),現在只要添加上 --initialize 參數即可,像這樣  >mysql --initialize.運行這個命令之后會自動初始化數據庫,建立缺省的數據目錄并構建數據庫。同時,還可以生成一個帶有高強度隨機密碼的用戶(但這個密碼被標記為過期,也就是說第一次登陸之后,管理員要通過 SET PASSWORD 修改密碼)

我們給參數 --secure-file-priv (指定LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE()命令的作用路徑)添加了一個安全的默認參數(之前的版本沒有默認值)(WL#6782),主要是為了文件讀寫權限的作用域安全而考慮。加了這個參數后,如果用戶的配置文件有不安全因素,數據庫在啟動時給出警告提示

我們重新定義了 --ssl 參數進行強制加密連接了(WL#6791)。以前,即使 MySQL 客戶端在連接服務器時指定了 --ssl 參數,如果沒有執行加密連接,依然可以連接服務器。現在指定了這個參數,如果沒有 SSL 加密連接,連接就會失敗。同時,我們也給 mysqlbinlog 添加了 SSL 支持(WL#7198)。

在安裝期間,我們提供了“最佳努力”SSL 安裝進程。如果安裝成功,MySQL 服務的配置文件也可以修改成新生成的證書和密匙(WL#7706)。不管它什么時候在服務器里啟用,我們都會確保 SSL 的使用。如果 SSL 選擇定義了 none,那么如果服務器支持這樣做,libmysql 客戶端就會嘗試 SSL 連接。如果 SSL 連接不可用,那么 libmysql 客戶端將會使用未加密的連接。參見 odd Farmer’的文章“SSL/TLS in MySQL 5.7” 和 “對第三方產品來說 TLS 計劃的意義“.

我們已經增加了— require_secure_transport 服務器選項,這可以讓 MySQL 服務拒絕任何沒有使用 SSL 的 TCP/IP連接。在這之前,MySQL 服務僅僅提供了一個為獨立用戶賬戶在多種賬戶管理報表中使用 REQUIRE SSL 條件的機制。

我們改變了 sql_mode 的默認值,包含了 NO_AUTO_CREATE_USER(WL#8326)。這是為了防止 GRANT 語句在無意和自動的創建新的用戶時而沒有提供/設置任何權限信息。

安全特性

除了“默認安全”的安裝之外。我們也增加了許多個性安全來幫助用戶保持他們的數據庫實例遠離意外使用。這包括了較好的數據加密,較好的密碼處理,較安全的傳輸層等等。

目前,我們也支持了多 AES 加密模式 (WL#6781)。我們也增強了我們的高級加密標準(AES)加密/解密函數 AES_ENCRYPT() 和 AES_DECRYPT() 的安全強度——通過增加對較大密匙長度和不同的塊模式的支持。參見 Georgi Kodinov 的文章“在 MySQL5.6.17 里理解和滿足你的 ASES 加密需要“。

我們在 mysql.user 表里增加了一個時間戳字段用于保存密碼最后一次改變的時間(WL#7131)。這為密碼輪換政策的實行提供了基礎。參見 Todd Farmer 的文章 “MySQL 實施密碼策略“。

我們通過擴展 CREATE USER 和 ALTER USER 命令實現了對用戶賬戶(登陸權限)的可用(解鎖)或不可用(加鎖)的設置(WL#6054)。參見 Todd Farmer 的文章“構建一個好的 CREATE USER 命令“.

我們擴展了內置身份認證插件用以支持代理用戶(WL#7724)。MySQL 已經有一個可以支持主要用戶功能的代理用戶的概念。比如 SQL 角色:從權限分配里抽象出用戶標識/身份的功能。這允許多個用戶——在不同的方式中的定義,日志,和審核——分享一個單獨的管理權限的設置。在部署很多個已經定義了權限的用戶時,這提供了操作上的便利,但是直到現在,通過擴展身份認證插件,代理用戶促使了這種改變。這清除了以前的限制。參見 Todd Farmer 的文章 “在 5.7.7 中使用擴展的代理用戶模仿角色“。

我們還增加了用戶名的最大長度,從 16 個字符倒 32 個字符(WL#2284)。

我們已經在 CREATE USER 和 DROP USER 命令里實現了 IF [NOT] EXISTS 條件判斷。這可以讓分布式賬戶在復制組內使用非同步賬戶事件時(故意地),復制而不會觸發復制失敗。這也簡化了賬戶管理操作的腳本。見在 Bug#15287里的特性請求。

InnoDB 的本地分區

我們已經增加了對 InnoDB 本地分區的支持(WL#6035)。到目前為止,對 InnoDB 分區的支持依賴于 ha_partition 處理器,這個處理器可以為每一個分區創建一個新的處理器,當使用很多分區時,這個處理器也相應的浪費了很多資源。通過在 InnoDB 內對本地分區的支持,你可以使用更少的整體資源(見: bug#62536, bug#37252, 和 bug#70641)。InnoDB 的本地分區也為較好的整體分區鋪平了道路。這包含諸如并行查詢進程,改進分區裁剪(由于較精確的計數統計),外鍵支持,全局二級索引,和在分區表上的全文本搜索之類的功能。作為這項工作的一部分也已經從分區處理器類中的特性部分分離出了它自己的分區接口(WL#4807)。這是為了重構成模塊化,并且從其他的服務器基礎代碼中解耦分區引擎。

另外,我們為分區表增加了對索引條件下推(ICP) 的支持 (WL#7231, 來自于 Bug#70001)。我們也增加了 EXCHANGE PARTITION 命令的 對[{WITH| WITHOUT} VALIDATION]條件的支持 (WL#5630, 來自于Bug#57708)。我們還為已分區的InnoDB 表增加了可移動表空間 的支持。見 Mattias Jonsson的文章“MySQL 5.7.4 目前對InnoDB分區支持可移動的表空間“。

InnoDB 的通用表空間

我們新增了CREATE TABLESPACE 語句來創建一個通用表空間(WL#6205WL#8109)。這個功能可以讓用戶自由的選擇表和表空間之間的映射,例如,表空間的創建和這個表空間應該含有什么樣的表。這也讓在同一個表空間的用戶或客戶對所有的表分組,因此在文件系統的一個單獨的文件內持有他們所有的數據。我們也為通用表空間實現了元數據鎖 (MDL)(WL#7957)。這主要是為了滿足 InnoDB 中新的普通表空間,也為了已有的 NDB 集群通用表空間。

InnoDB 臨時表性能

優化普通 SQL 臨時表性能是 5.7 的目標之一。首先,我們通過避免持久化臨時表到磁盤時的不必要的步驟,使得臨時表的創建和移除成為一個輕量級的操作。我們將臨時表移動到一個單獨的表空間(WL#6560) ,因此對于臨時表的恢復過程就變成了一個在啟動時僅僅簡單的重新創建臨時表的單一的無狀態步驟。我們去掉了臨時表中不必要的持久化(WL#6469)。臨時表僅僅在連接/會話內可見,創建它們,通過服務的生命周期綁定它們。我們通過移除不必要的 UNDO 和 REDO 日志,改變緩沖和鎖,從而為臨時表優化了 DML(WL#6470) 。我們增加了 UNDO 日志的一個額外的類型 (WL#6915),這個類型是不可 REDO 日志和保留在一個新的單獨的臨時表空間。這些 non-redo-logged UNDO 日志在恢復期間不需要,僅在回滾操作是需要。

第二,我們也為臨時表設定了一個特別類型,我們稱之為“內在臨時表”(WL#7682WL#6711)。內在臨時表和普通臨時表很像,只是內在臨時表使用寬松的 ACID 和 MVCC 語義。目的是為了支持內部模塊的內部用例, 例如,優化器為了中間操作而要求輕型和超快速的表。那么我們就讓優化器使用 InnoDB 的“內在臨時表”作為內部儲存(WL#6711)。最終,我們讓 InnoDB 的默認引擎使用 內部臨時表 。見 Krunal Bauskar 的文章“MySQL 5.7: InnoDB 內在表“。

緩沖池 —— 卸載和加載

我們改進了緩沖池卸載和加載場景(WL#6504)。目前可以卸載每個緩沖池中僅最熱的 N% 頁。加載操作減少了對用戶活動的破壞性,因為現在的加載是在后臺為客戶提供服務的;也不會嘗試著太據有侵略性和從服務新的客戶請求中占據太多的 IO 資源。見 Tony Darnell 的文章 “MySQL 卸載和加載InnoDB 緩沖池“。

我們也通過默認和改變默認百分比到 25% 的方式改變服務器使用緩沖池加載和卸載 (WL#8317)。這也使得在 1. 支持“熱”工作數據設置和 2. 關閉和啟動次數之間形成好的默認平衡。

工具

服務器附帶一個實用程序或腳本(工具)的設置。這是為了提供和增加更多的工具。我們也想去除“腳本”而使用 C/C++ 從而改進可移植性,覆蓋更多的使用場景(一個可以運行在所有環境下的腳本)。

我們實現了一個新的 MySQL 服務器工具叫做 mysqlpump,通過 mysqldump (WL#7755)調用——但不是 100% 的兼容。這個新工具的主要特點是可以執行并行的備份和存儲操作(已有的 mysqldump 將繼續被支持)。

我們也擴展了 innochecksum 工具的功能(WL#6045)。目前可以指定校驗值算法(innodb/crc32/none),使用指定的算法重寫當前的校驗值,即使當前的校驗值不可用也可以重寫,允許在終止程序之前指定最大不匹配校驗值。innochecksum 目前也可以在多個表空間文件和相同表空間的多個文件上操作。見 Anil Toshniwal 的文章“Improving Innochecksum“。

我們重寫了mysql_upgrade 工具 (WL#7308),這個工具解決許多已報告的 bug,也使得mysql_upgrade 更加的穩健和易于維護。例如,它解決了 Nicholas Bamber 報告的Bug#65288 和Florian Weimer 報告的 Bug#71579 。

我們增加了 SSL 選項和支持 mysqlbinlog 客戶端程序(WL#7198),這允許系統管理員通過安全連接執行遠程 binlog 查詢 (--read-from-remote-server) 。這是上一版沒有 SSL 支持的 MySQL 客戶端程序遺留下來的。

我們已經轉化 mysql_secure_installation 腳本為 C/C++(WL#6441)。這個程序現在可以使用 C API(libmysql) 執行指定的命令直接連接到服務器。這取消了對于在文件系統中一個臨時選擇文件來存儲用戶提供的密碼的需要。

為了讓程序可以在所有平臺上使用——特別是 Windows,也為了提供更好的用戶體驗,覆蓋更多功能,提高安全性而重新設計程序,我們開始了轉 換mysql_install_db 腳本為 C/C++ (WL#7688)。在 5.7 之后的版本里,我們決定將這個功能回歸到服務器本身(見 WL#7307)。在 5.7 里 mysql_install_db 程序,可以被使用,但是不再被需要,我們計劃在以后的版本里刪除這個功能。

社區貢獻

服務器端語句執行超時(WL#6936) :這是基于 Davi Arnaut 提交的貢獻(Bug#68252)。這個功能是為頂層 SELECT 語句的執行實現了一個服務器端的時間限制。一定的時間之后,語句就會被中止而不會影響到會話(連接)或者事務上下文。見 Praveen Hulakund 的文章“服務端 SELECT 語句超時“。

多用戶級鎖:允許通過 GET_LOCK() 獲得多個鎖(WL#1159)。用戶級鎖經常用在訪問一些資源時而表或者行級鎖不適用的情況下實現互斥 。這個功能允許每個連接都擁有多用戶級鎖。而這個功能就源于Konstantin Osipov 的貢獻(Bug#67806)。見 Dmitry Lenev 的文章“一個貢獻者的故事“。

觸發器

BEFORE 觸發器沒有為非空列執行 (WL#6030) :這個功能確保了在 SQL 語句結束后對列約束的檢查。這符合 SQL 標準。在 5.6 和早期版本中,MySQL 對列約束的檢查太早。見由 Peter Gulutzan 報告的Bug#6295,和 Dmitry Shulga 的文章“MySQL 的 BEFORE 觸發器和非空列“.

表的多觸發器(WL#3253) :這個功能為每個動作(INSERT, UPDATE, DELETE) 和時機(BEFORE or AFTER)都擁有多個觸發器成為可能。這也符合 SQL 標準。見 Dmitry Shulga 的文章“為動作/時機的相同值支持表的多觸發器“。

IGNORE 子句

定義和重新實現 IGNORE (WL#6614) :這個工作適當的定義了 IGNORE 子句的意思和處理,這是 MySQL 對 SQL 標準的擴展。重新實現 IGNORE 以便一致的通過對所有 SQL 語句的支持,也讓 IGNORE 更加易于維護。見 Bug#30191,Bug#49539,Bug#55421,Bug#54543Bug#54106Bug#49534Bug#47788Bug#46539, 和 Bug#46425。 見 Abhishek Ranjan 的文章“改進 MySQL IGNORE 的實現“.

STRICT 模式

定義和重寫 STRICT 模式 (WL#6891):我們已經讓 STRICT MODE 的行為一致的通過了對所有 SQL 語句的支持。我們也讓 STRICT MODE 默認的支持事務存儲引擎 (WL#7764)。為了允許語句跳過(多)行而讓 IGNORE 子句下調錯誤為警告,否則會讓整個語句中止。而 STRICT MODE 卻在做相反的事情——將警告升級為錯誤。類似于 IGNORE,STRICT MODE 也沒有提前做一個清晰而一致的定義。因此,實現就出現很多這樣的 Bug,像Bug#42910Bug#5929Bug#43880Bug#48637Bug#5912, 和 Bug#5913。見 Abhishek Ranjan 的文章“在 MySQL 中改進 STRICT MODE “。

錯誤報告和日志

介紹一個在5.7版本中獨立的錯誤代碼(WL#8206):在5.7版本中,它為新的服務器錯誤消息實現了一個單獨的范圍的數值。這些代碼目前是連續編號的,從1000開始。我們的客戶端使用的錯誤代碼范圍是2000。問題是第一個區域的錯誤代碼已經累積到1974,這意味著這兩個范圍將會重疊,這樣就很難區分是服務器端的錯誤還是客戶端的錯誤。現在新的5.7版本的服務器將會從3000開始。

錯誤報告——棧診斷域(WL#6406) :它實現了以SQL標準定義的棧診斷域。獲得診斷(GET DIAGNOSTICS)聲明已經擴展了獲得【棧】診斷(GET  [STACKED] DIAGNOSTICS)

錯誤報告 —— 大多數語句都應該清除診斷區(WL#5928) : 這讓 MySQL 符合清空診斷區域的 SQL 標準,也解決了 Bug#35296Bug#43012, 和 Bug#49634

錯誤日志 —— 允許冗余控制(WL#6661, WL#6755) :這讓 DBA 知道,當寫錯誤日志(ERROR/WARNING/NOTE),MySQL 服務器應該怎樣進行冗余控制。這也支持了多種時間戳格式(UTC 時間戳)的打印,并廢棄已有的 fprintf(stderr, …) ,在服務層使用新的內部日志 API。

為在 Unixoid 平臺的 Syslog 增加本地支持 (WL#7793) :這為日志服務器輸出到服務器的本地系統日志提供支持,見由 Kyle Joiner 記錄的 Bug#55370。并隨后有 Simon Mudd 和 Marc Alff 進行了升級,見 Tatiana 的文章“MySQL 的日志:系統日志&事件日志錯誤日志“.

MySQL 客戶端

使用 Syslog 記錄用戶交互命令日志 (WL#6788) : 這個工作引入一個新的選項,--syslog,  該選項可以開關 logging 屬性就像 sudo_user (或者user), mysql_user, connection_id, db_server, DB, 和在交互 session 輸入的查詢. 這是應一些用戶的審計需求,比如要求將所有交互命令行的輸入即時記錄到 syslog.

客戶端協議追蹤(WL#6226) : 這項目工作在客戶端代碼包中添加了鉤子用來追蹤協議事件,如向服務端發包,接收服務端返回和心跳鑒定. 這提供了一個機制可以從客戶端的視角收集客戶端和服務端的連接性能。


客戶端-服務器協議

為了(WL#8077)的轉義,就得知道字符串類型,因此擴展了mysql_real_escape_string():我們為函數mysql_real_escape_string_quote()增加了一個“引用類型”的參數。這是為了明確單引用字符串和雙引用字符串之間的區別。但這破壞了ABI,因此它不會回歸到5.6。

擴展了現在的OK包:為了讓服務端發送額外的信息而擴展的客戶端-服務器協議的OK包,例如,服務器狀態改變. 服務器現在默認的發送關于SET character_set和USE database命令的信息。這個避免了這樣的狀況,例如,SET NAMES big5之后服務器假定客戶端將會發送big5編碼的數據,然而客戶端仍然使用latin1編碼.

Session-Specific 的狀態標志 (WL#6885) :這個標志可以讓客戶端通知服務端會話狀態的改變。這個功能的一種用法是檢查是否可以遷移一個用戶的會話環境到一個負載均衡內或集群環境內的另一個物理連接。

GIS: InnoDB 空間索引

我們已經在InnoDB 內實現了空間(R-tree) 索引(WL#6968,  WL#6968,  WL#6745) : InnoDB空間索引可以被用于所有已有的為MyISAM空間索引開放句法規則。另外,InnoDB 空間索引支持完整的事務,ACID和MVCC 特性(以及隔離層)。空間索引采用了謂詞鎖的方式防止幻想問題。

我們已經增加一個新的InnoDB內部類型:DATA_GEOMETRY,我們將所有的MySQL的GEOMETRY 數據都映射到這個新的內部數據類型(WL#6455)。我也已經擴展了CHECK TABLE,目的是為了CHECK TABLE 能夠判斷任何空間索引是否是有效的(WL#7740)。母校CHECK TABLE 檢查R-tree結構的有效性并確保入口數量匹配群集的索引。見 Jimmy Yang的文章“InnoDB Spatial Indexes in 5.7.4 LAB release“.

GIS:幾何功能和格式

經過各種開源的幾何引擎的仔細評估后,我們決定用 Boost.Geometry 代替我們原來的 GIS 算法。對于那些從源代碼中構建 MYSQL,去閱讀我們添加的新的 CMake options 是非常重要的。改變幾何引擎并不是一個簡單的任務,所以許多關于 GIS 的嘗試都投入到了這個工作(WL#7220,  WL#7221,  WL#7224,  WL#7225WL#7236WL#7280,  WL#7420WL#7929)中。在這過程中,我們已經修改了許多漏洞并且為許多額外的 SQL/MM 標準空間操作提供了支持作為增加的 GIS 的成就的一部分,我們已經開始清除 GIS 函數的命名空間。額外的構造函數和這些數據類型(Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon and GeometryCollection)有相同的名字并且有計算最小包圍矩陣(MBRs)的功能,現在所有空間函數用標準的“ST_” (spatio-temporal)為命名前綴的規定,并且函數的名字沒有那個前綴就被反對(WL#8055)。

支持兩個新的導入導出格式, GeoJSON 和 geohash。這些支持已經豐存的 WKT 和 WKB。新的 GeoJSON functions ST_AsGeoJSONandST_GeomFromGeoJSON 將會解碼和編碼 GeoJSON 文檔 (WL#7444)。新的geohash ST_Geohash,ST_LongFromGeohash,ST_LatFromGeohashandST_PointFromGeohash 會和 geohash 目前功能一樣(WL#7928)。

我們還添加了一些幫助功能 (WL#8034): ST_Distance_Sphere, ST_MakeEnvelope, ST_IsValid, ST_Validate and ST_Simplify。其中 ST_Distance_Spheremay 可能是最激動人心的 。而 MySQL 的地理信息技術支持仍然只使用 2d 平面,ST_Distance_Sphere 將計算與給定半徑的球體兩個點(或多點)之間的距離。兩個新的膜生物反應器的功能也得到了補充:MBRCoveredByandMBRCovers (WL#7541)。因為 MBR 函數在 MBR 做計算代替精確的形狀,計算比ST_ functions 更快。

看看他們是怎么結合 的,參見 Matt Lord 的文章,“MySQL 5.7 and GIS, an Example


多源復制

我們已經實現了多源復制  (WL#1697)。它允許一人從結點從多個數據源/主結點復制,但沒有額外的沖突檢索和處理。一個應用場景是委托一個子結點做數據聚合或備份。此前我們通過 MySQL Labs 做了第一次發布 ,當前版本考慮了當時從社區得到的大量反饋。參見 Shivji Jha’的文章“MySQL-5.7.6: Introducing Multi-source replication“。

復制 — 多線程站(MTS)

我們已經實現了內部多線程站(WL#6314)。受益于此實現 (--slave-parallel-type=LOGICAL-CLOCK) 子結點可以應用并行事務,即便在單個數據庫或模式,只要他們具有不相交的讀寫設置,參見 Rohit 的文章“MySQL 5.7 Enhanced MTS: configuring slave for Intra-database parallelization“。

我們還實現了有序提交(順序一致性)(WL#6813)。這將保證子結點應用多線程并行提交時在主結點上的順序是相同的。這也意味著如果主結點沒有擴展數據庫的狀態,從結點也不會。當應用從從結點讀取時需要保證和主結點的狀態一致,這是強制約束自從 WL#6314,它可以并行的從結點可以執行多個事務,多個從結點可能會修改一個數據庫。

我們允許復制從結點到臨時故障點后自動重試事務 (WL#6964)。在此之前,只有 non-MTS 復制從結點并嘗試執行臨時故障后的事務。見 Yoshinori Matsunobu 提交的 Bug#68465 。通過使用更精確的算法來確定哪些事務是非沖突的(WL#7165),最后我們改進了多線程站的性能,這使得當使用 --slave-parallel-type=LOGICAL_CLOCK 時可以并行執行多個事務,從而提高復制的性能。

半同步復制

當半同步復制功能(WL#7169)開啟時,我們已經實現了一個主結點可以同步等待 N 個從結點應答而不是一個,通過選擇 N 個從結點(N>1),可以增加容錯的靈活性。同時改善事務的穩定性,因為事務被主結點外化后,兩個結點的持續性會更好一些。此外,我們現在只在 ACK 被接收后(WL#6355)才做外化。這樣,使用半復制以后可以真正的做無故障轉移。如果主結點崩潰,從結點依然可以保證是最新的。此實現可以讓主結點等待 ACK 發生在存儲引擎準備并寫入二進制日志后,向存儲引擎提交之前。參見 Libing Song的文章“Loss-less Semi-Synchronous Replication on MySQL 5.7.2“。最后,我們已經通過使用單獨的線程來發送和接收半同步確認(WL#6630)來減少半同步復制延遲。所以事件和 ACK 流現在可以同時發送和接收。


復制 — GTID

如前面提到的,我們提供了一種啟用 GTID 的方法(WL#7083),在此過程中,允許讀取和寫入,并且服務器不需要同步。在此項工作之前,用戶需要停止所有的更新和服務器同步并在稍后重啟服務器。不管 GTID_MODE 的值為何,都要這樣做(WL#7592)。除了確保一致性的操作,還有一種情況就是,你可能丟失 GTID_EXECUTED 和 GTID_PURGED 的值(細節請參考WorkLog entry)。(本來是 WL#7083 的一部分)。還可以參考一下 Sven Sandberg 的文章:“在 MySQL 5.7.6 中不停機啟用全局事務標識符 GTID“。

最后,我們實現了 GTID 的協議支持,以便于客戶端感知到GTID。我們已經實現了一套機制,用于收集通過線路發送的響應包中必要的 GTID 設置(WL#6972)。同時,還在 MySQL 協議的響應包中添加了一個跟蹤器(WL#6128)。這樣做的目的是可以傳輸連接器的信息,這些信息是為實現會話一致性而收集的會話狀態。

復制 — 重構

我們已經創建了一個穩定的接口,這個接口對 MySQL Group Replication 和其它服務器插件都很有用(WL#8007 和 WL#8202)。服務器插件現在可以以服務器回調的形式獲知服務器的事件了。同時,我們將 MySQL 復制流中的事件反串行化分離到一個單獨的模塊中(WL#7440)。這次重構是為了打破服務器核心與復制框架之間的依賴關系。

其它復制特點

  • 非阻塞式 SHOW SLAVE STATUS (WL#6402) : 這項工作為 SHOW SLAVE STATUS 添加了一個非阻塞選項。新的選項使 SHOW SLAVE STATUS 與 STOP SLAVE 并行運行時是非阻塞的 (當從線程在等待進行大規模事件的 SQL 線程時,停止它可能要花費很長的時間)。

  • 給 mysqlbinlog 添加 Idempotent Mode (WL#6403) :這項工作給 MySQL 服務器提供了一種 idempotent 模式操作。在這種模式下,當從 binlog 文件中應用基于 ROW 的事件時,服務器會忽略錯誤。當數據庫管理員想使用 mysqlbinlog 回放 binglog 時這個模式將很有用。對于沒有包含全部數據的 MySQL 服務器,忽略可以預料的 duplicate-key 和 no-key-found 錯誤也相當有用。

  • 對于 ROW 事件給 mysqlbinlog 添加 Rewrite-DB 選項(WL#6404):這項工作為 mysqlbinlog 添加 rewrite-db 選項支持。這樣一來,一個基于 ROW 的事件可以應用到一個不同的數據庫/架構。例如:當從 binlog 中讀取基于 ROW 的事件時用 "to_db" 替換 "from_db"。

  • Binlog_sender:不再重新分配(WL#7299):這項工作實現對移除發送緩沖非必要重分配線程轉儲的優化。用戶可以看到,在主線程產生的每個線程轉儲中,CPU 使用率將明顯減小。參見 Mark Callaghan 提交的 Bug#31932

  • 將狀態變量移動到復制性能架構表(WL#7817):為了滿足多源復制的需求,這項工作將復制系統變量移動到性能架構表。這樣就可以從每個源來監控這些變量,而不是簡單地作為全局變量。

  • 使主從同步選項獨立于從線程之外(WL#7796):這項工作添加了一個新的SQL函數WAIT_FOR_EXECUTED_GTID_SET,這個函數將會使主從同步選項獨立于從線程之外。如果從線程沒有運行WAIT_FOR_EXECUTED_GTID_SET(GTID_SET [, TIMEOUT])函數,那么從線程將會一直等待,直到成功 (0)或超時 (1)。

  • 優化被動從線程的GTIDs —— 將GTIDs存儲進表中(WL#6559):這項工作添加了一個選項,可以將GTIDs存儲到一個表而不是在二進制日志中。其應用場景可能是:一個從線程只用于擴展讀取規模,不會成為主線程,因此對于二進制日志中事務的處理來說沒有任何用處,但是,相關的GTID功能還是有可能用到的(例如啟動故障轉移到新的主線程)。

  • 等待更多事務進入Binlog Group Commit(BGC)隊列(WL#7742):這項工作添加了引入手動延遲的新選項 --binlog_group_commit_sync_delay 和 --binlog_group_commit_sync_no_delay_count,新選項可以使二進制日志組提交過程暫停。這增加了從磁盤刷新和同步更多事務的可能性,因此減小了創建一個事務組花費的時間(組越大,同步操作越少)。正確地調優之后,在不比較主線程的吞吐量的情況下,它可以使從線程的性能提高數倍。

  • Binlogging 準備好的分布式事務(WL#6860):我們對復制添加了完整地分布式事務機制。分布式事務允許客戶端參與二相提交協議。分布式事務的狀態在數據庫中持續準備著;這意味著一個準備好的分布式事務將會在客戶端重連和服務器重啟后任然存在。這項工作修復了Bug#12161

其他改進

  • InnoDB:默認 ROW_FORMAT=DYNAMIC (WL#8307):這個引入了一個新的全局變量 innodb_default_row_format,指定默認的 ROW_FORMAT。默認設置為 DYNAMIC。可選的值有: REDUNDANT, COMPACT 和 DYNAMIC。

  • PERFORMANCE_SCHEMA,添加列 THREADS.THREAD_OS_ID (WL#8853):這個表明 “TID”,或者是線程/任務 identifier,通過底層操作系統定義。例如 Linux,對應的是 gettid()。

  • Sys Schema 進展報告(WL#8460):這個在系統模式上添加了長期運行事物的進展報告,通過把追蹤工作 估計/完成 的階段完成百分比放入到進展列表/會話 視圖。

  • 報告支持 (WL#7804):這個實現了一個系統模式的步驟,允許 DBA 簡單的從一個 MySQL 實例收集診斷的數據,形成調查和報告。

  • 讓 InnoDB 填充可設定的因素 (WL#6747):這個可以設定每個索引的 merge_threshold。直到現在,已經修復完成了 50%。如果頁面填充的數據量小于 merge_threshold,比如,當通過一個 UPDATE 刪除或一行或者進行縮短,InnoDB 會嘗試合并到相鄰的頁面。這個提供了一個方式來降低 InnoDB 的覆蓋硬盤腳本,也因為額外的頁面合并而增加額外的工作量。

  • 支持 32k 和 64k 頁面 (WL#5757):這個添加對 32k 和 64k 頁面大小 (默認為 16k)的支持。更大頁面大小可以幫助改善壓縮率,因此可以提供更好的數據壓縮。并且更大的頁面大小允許更多 “on page” 或者 “inline” 的 BLOBs 存儲和大型 VARCHAR/TEXT 字段存儲,因此提升 I/O 性能。

  • InnoDB 高優先級事物(WL#6835):這個實現了高優先級事物的 InnoDB,比如,事物不會在一個死鎖場景被中止。這樣可以更好的支持 MySQL Group Replication,一個事物不會在一個副本中中止,在另一個里面提交。

  • 確保 5.7 能從 5.6 中平滑的進行在線升級 (WL#8350):這個確保從 5.6 到 5.7 的在線升級,無需指定 --skip-grant-tables 作為中間的步驟。

  • 從 MyISAM 移動插件和服務器表到事務性存儲 (WL#7160):這個使得 InnoDB 默認存儲引擎用于 插件和服務器系統表 (MyISAM remains optional)。

  • DTrace 支持 (WL#7894):Server 5.6+ 包中我們添加了完整的 Dtrace 支持到 MySQL,而且支持 Oracle Linux 6+。

  • InnoDB 表 Update_time (WL#6658):這個實現了內存的 InnoDB 表 UPDATE_TIME 維護。這個功能之前在 InnoDB 中已經失效,因為用戶再三要求,現在已經加上。詳情請看 Bug#2681

  • 截斷 TABLE 語句,具備原子性 (WL#6501):這個使得內部 InnoDB TRUNCATE TABLE 語句具備原子性,通過使用相同空間 ID 來重新初始化原始表空間頭部,物理上截斷它的 .ibd 文件。

  • 完善連接 ID 處理 (WL#7293) :這個避免了任意仍然在使用的連接 IDs 復用。詳情請看 Bug#44167

  • 提供一個選項來拒絕存儲引擎列表的用戶表創建 (WL#8594) — 這個是 Thayumanavar Sachithanantha 提供的一個命令行選項 --disabled-storage-engines,提供給 DBA,禁用存儲引擎列表,然后防止用戶使用任意特定的存儲引擎(錯誤的)。 這個支持用戶有防止使用策略的用例,比如,MyISAM 和其環境。

關于廢棄和移除方面的詳細描述,請看這里,關于系統默認設置方面的改進請看這里

以上,感謝您使用 MySQL!

 本文由用戶 碼頭工人 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!