【轉載】MySQL5.6.27 Release Note解讀(innodb及複製模塊)

新功能

 
問題描述(Bug #18871046, Bug #72811):

主要爲了解決一個比較「古老」的MySQL在NUMA架構下的「swap insanity」問題,其表現爲儘管爲InnoDB buffer pool分配了足夠多的內存,但依然會產生swap。而swap對數據庫系統性能而言是比較致命的。html

當咱們配置的buffer pool超過單個node的內存時,例如總共64GB內存,每一個節點32GB,分配buffer pool爲40GB,默認狀況下,會先用滿node 0,再在node1上分配8GB內存。若是綁定到node 0上的線程須要申請新的內存時,不是從node1上申請(還有24GB空餘),而是swap node0的內存,再作申請。node

這個問題在社區討論了好久,大神Jeremy Cole 對該問題有寫博客作過詳細的介紹(http://blog.jcole.us/2010/09/28/mysql-swap-insanity-and-the-numa-architecture/mysql

解決:linux

增長了一個只讀的新參數innodb_numa_interleave選項,當開啓該選項,能夠容許在NUMA架構下采起交叉分配內存的方式。git

在啓動MySQL時,採用MPOL_INTERLEAVE方式分配內存,如上例,在啓動時每一個node上分配20GB內存,保證每一個node依然有空閒內存可用;在完成InnoDB buffer pool內存分配後,再將內存分配策略設置爲MPOL_DEFAULT,以後的線程申請內存,都在各自的節點完成。github

 
 
 
 
 
 
 
 
 
 
 
 
 
 

補丁:sql

 
 
 
 
 
 
 

https://github.com/mysql/mysql-server/commit/242fa2c92de304637e794e531df1f1b86b8d1dee數據庫

 
 
 
 
 
 
 

https://github.com/mysql/mysql-server/commit/d2578b57ba7d90a00281ae124a1cd6c83193f62asession

 
 
 
 
 
 
 
 

InnoDB bugfix

問題描述:架構

 
當一個表被驅逐並從新導入時,若是表的內容是空的(例如先插入大量數據,再一次全刪除時,auto_increment不爲0),就會致使AUTO_INCREMENT的值被重置。(Bug #21454472, Bug #77743)
 
 
 
 
 
 
 
 

這是由於每次打開表時,老是經過計算表上記錄最大自增列值的方式來從新設置,當表被打開時,若是沒有數據,AUTO_INCREMENT就會被重置成最小值。

解決:

在驅逐表時,將這個表的AUTO_INCREMENT值存儲在內存中(dict_sys->autoinc_map),當表從新讀入時,再恢復其AUTO_INCREMENT值。

這個Fix並不算一個完整的修復,當實例重啓時,AUTO_INCREMENT依然會被重置(參閱bug#199), RDS MYSQ已經Fix了這個bug,可以持久化自增列到物理文件中,在重啓後不會丟失。

補丁:

https://github.com/mysql/mysql-server/commit/d404923aad4693dc152d02461f858d7ef218c336

 

問題描述:

Memcached的一段開啓事務的代碼在assert中調用,而根據assert的文檔定義(

http://man7.org/linux/man-pages/man3/assert.3.html

),他的行爲是未知的,受NDEBUG控制,可能assert會被定義成空函數,致使assert中的函數調用被忽略掉。這個bug在某些平臺下可能極易觸發。使用memcached的同窗須要注意下。 (Bug #21239299, Bug #75199)

 
 
 
 
 
 
 

解決:

將函數調用從assert中移出來,只assert函數返回值。

補丁:

https://github.com/mysql/mysql-server/commit/db5dc6fd3abe855685a554bc3c555b1b63914b60

問題描述:

在ARM64平臺上, GCC的內建的TAS操做函數__sync_lock_test_and_set

 
 
 
 
 
 
可能不許確,這和平臺內存模型有關,鎖的行爲錯誤,致使進一步的數據損壞。(Bug #21102971, Bug #76135)
 
 
 
 
 
 
 

該bug最初從MariaDB爆出,參考MDEV-6615 https://mariadb.atlassian.net/browse/MDEV-6615

 

解決:

若是定義了__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)/ __atomic_clear(ptr, __ATOMIC_RELEASE)操做,則優先使用該函數進行變量設置,不然若是是X86平臺,使用__sync_lock_test_and_set ,其餘狀況,在編譯階段報錯。

補丁:

https://github.com/mysql/mysql-server/commit/f59d68eeae37338d7b25f2571407e763fa897e15

 

問題描述:

InnoDB shutdown時須要調用三次trx_purge操做,每次處理300個undo log page,最終處理900個undo log page,可是shutdown須要等待purge線程退出,,這可能須要耗費比較長的時間,shutdown會更耗時。(Bug #21040050)

 
 
 
 
 
 
解決:
1. 在每loop TRX_SYS_N_RSEGS個回滾段時,只調用一次trx_purge,以前的邏輯會調用兩次
2. 在shutdown時一次處理的batch size臨時調整到最多20,
 

補丁:

https://github.com/mysql/mysql-server/commit/3e8202ff443909e93231d453a3f1560b5a5ce3cb

 

問題描述:

在READ COMMITED隔離級別下,併發replace into操做可能致使惟一二級索引損壞,惟一鍵約束失效。這主要是鎖繼承邏輯錯誤致使,具體的見以前的一篇月報分析http://mysql.taobao.org/monthly/2015/06/02/

解決:

調整鎖繼承邏輯,若是是相似REPLACE INTO這樣的操做,須要進行鎖繼承。以前月報有詳細分析。

補丁:

https://github.com/mysql/mysql-server/commit/608efca4c4e4afa1ffea251abda675fcc06efc69

 
 
問題描述:
IBUF_BITMAP_FREE的值表示一個page可用的空閒空間數據範圍, 這個值比實際的空閒空間值要大些,當INSERT操做是經過更新一個已存在但被標記刪除的記錄來完成時,InnoDB沒有更新對應page在IBUF BITMAP中的IBUF_BITMAP_FREE值。
 
解決:更新bitmap

補丁:

https://github.com/mysql/mysql-server/commit/641ab6f36813516255738ba25d3c6b721189832e

 
問題描述:
當innodb_force_recovery大於3時,innodb在redo 被apply以前被設置成read only模式,致使沒法恢復。另外從當前版本開始,當force recovery 大於3時,支持drop table,這能夠協助將損壞的表清理掉,避免重複crash。
 
解決:
在代碼中,增長了一個新的變量high_level_read_only,當srv_read_only_mode開啓或者force recovery 大於3時,將該變量設置爲true. 在除了DROP TABLE以外的DDL和DML執行時,會作檢查。也就是說,force recovery 大於3時,drop table是惟一能夠作的操做; innodb_read_only模式下,依然不容許全部變動操做。
 
 

複製

 
本次版本更新修復了大量的複製bug
 
問題描述:
若是一個事務在備庫apply時須要等待行鎖超時,而且repositories設置爲table模式,重試時可能觸發斷言錯誤。 由於在肯定重試時,事務狀態依然是active的,再次調用global_init_info函數會去開啓一個新的事務,觸發斷言(修復BUG16533802 引入的regression)
 
解決:
在超時重試以前調用rli->cleanup_context(thd, 1),將當前事務徹底回滾掉,恢復到非active狀態。
 
補丁:
 
 
問題描述:
當使用STATEMENT模式時,單條SQL更新多個表時,一個事務可能被錯誤的記錄到binlog中。
以下所示:
CREATE TABLE t1(c1 int) ENGINE=InnoDB;
CREATE TABLE t2(c1 int) ENGINE=InnoDB;set session binlog_format=’STATEMENT';START TRANSACTION;
UPDATE t1,t2 SET t1.c1 = 0;
SAVEPOINT sp1;

 

UPDATE t1,t2 SET t1.c1 = 0;
SAVEPOINT sp2;

​COMMIT;

 
binlog中的記錄爲:
| master-bin.000001 |  229 | Query       |         1 |         340 | use `test`; CREATE TABLE t1(c1 int) ENGINE=InnoDB |
| master-bin.000001 |  340 | Query       |         1 |         451 | use `test`; CREATE TABLE t2(c1 int) ENGINE=InnoDB |
| master-bin.000001 |  451 | Query       |         1 |         539 | BEGIN                                             |
| master-bin.000001 |  539 | Query       |         1 |         648 | use `test`; UPDATE t1,t2 SET t1.c1 = 0            |
| master-bin.000001 |  648 | Query       |         1 |         737 | COMMIT                                            |
| master-bin.000001 |  737 | Query       |         1 |         825 | BEGIN                                             |
| master-bin.000001 |  825 | Query       |         1 |         934 | use `test`; UPDATE t1,t2 SET t1.c1 = 0            |
| master-bin.000001 |  934 | Query       |         1 |        1023 | COMMIT                                            |
| master-bin.000001 | 1023 | Query       |         1 |        1095 | BEGIN                                             |
| master-bin.000001 | 1095 | Query       |         1 |        1177 | SAVEPOINT `sp1`                                   |
| master-bin.000001 | 1177 | Query       |         1 |        1259 | SAVEPOINT `sp2`                                   |
| master-bin.000001 | 1259 | Query       |         1 |        1332 | COMMIT                                            |
+——————-+——+————-+———–+————-+—————————————————+
 
這是由於在決定寫binlog cache時,錯誤的寫到stmt_cache中(即時更新的都是事務表),所以在執行兩條update時都單獨寫入到Binlog中。並最後寫入了兩個savepoint語句。
 
(Bug #16621582, Bug #21349028)
 
 
解決:
若是是事務表,寫到trx_cache中
 
補丁:
https://github.com/mysql/mysql-server/commit/507051d967b134d7f29be759742d132423da601f
 
 
問題描述:
當dump線程在dump一個非活躍的binlog時被kill掉時,
本該退出這個日誌中的某些事件可能被忽略掉,致使備庫的數據丟失。這是修復Bug#19975697時引入的退化,影響5.6.24以後的版本
 
在發送Binlog時,有兩個循環:1.內循環遍歷單個binlog文件;2.外循環在文件間進行切換。內循環發現被kill掉後,進入外循環的邏輯,沒有檢查thd的kill標記,而是繼續下面的工做,可能致使當前文件中剩餘的log被忽略
 
(Bug #78337, Bug #21816399)
 
解決:
在退出內循環後,馬上檢查kill標記,若是線程被Kill了,則dump線程退出。
 
 
 
問題描述:
trigger中存在savepoint和rollback to savepoint可能觸發斷言失敗(debug版本),或者錯誤日誌中報以下錯誤,複製中斷:
[ERROR] Slave SQL for channel 」: Could not execute Write_rows event on table test.t3; Unknown error, Error_code: 1105; handler error HA_ERR_GENERIC; the event’s master log master-bin.000001, end_log_pos 1553, Error_code: 1105
 
咱們執行bug#76727中提供的case,從binlog記錄的序列以下
BEGIN
Table_map
Write_rows
Xid
 
BEGIN
Table_map
Table_map
Table_map
Write_rows
SAVEPOINT `event_logging`
Write_rows
Xid
 
因爲這裏SAVEPOINT `event_logging`是一個query event,他會去把已有的table map event作清理。致使後面的Write_rows沒法解析。
 
另一種場景是,即時SAVEPOINT後面沒有DMlL, 因爲在執行SAVEPOINT時會調用mysql_bin_log.write_event,將binlog flush 到IO CACHE,而且不帶STMT_END_F標記。若是以後沒有任何DML,沒有作合適的清理。這致使以後的一次DML不生成本身的TABLEMAP而是使用以前生成的,觸發備庫的解析錯誤。
 
 
解決:
1. 當在trigger/存儲過程當中執行ROLLBACK TO SAVEPOINT時,在函數binlog_savepoint_rollback中會清理table map標記(thd->clear_binlog_table_maps())。2. 對於trigger/存儲過程當中執行的SAVEPOINT操做,在調用函數MYSQL_BIN_LOG::write_event時,加上STMT_END_F標記,並重置TABLE MAP。
 
補丁:
 
 
問題描述:
當執行SHOW BINLOG EVENTS時,會持有Lock_log鎖,進行binlog讀取和釋放;而事務提交時,也須要持有Lock_log將cache寫到Binlog文件中。這會致使事務hang住,直到SHOW BINLOG EVENT操做完成。(Bug #76618, Bug #20928790)
 
解決:
只在確認顯示event的結尾位置時才加Lock_log保護,讀取和發送都不加鎖;這可能帶來的問題是,例如另一個線程作一次Purge,會產生warning。不過這是能夠接受的。
 
補丁:
 
問題描述:
在rotate時若出現因爲某些緣由致使生成新文件名出錯 (須要掃描目錄找到最大binlog序號)或者沒法建立新的binlog文件, binlog_error_action沒有處理,binlog中記錄了incident event,致使全部slave複製中斷。 (Bug #76379, Bug #20805298)
 
解決:
出現上述狀況時,也讓binlog_error_action進行處理。
 
補丁:
 
 
問題描述:
假設有gtid 1-3 已經寫入relay log,咱們正準備寫入第4個Gtid event,在以前的邏輯中,先寫relay log文件,再將Gtid加入到Retrieved_Gtid_Set中,若是這時在寫完Gtid 4 (但還沒加入到Retrieved集合)的事件到relay log,發生rotate,這時候Previous_Gtid的值爲(1-3),這時候若是發生重啓,假設4以後還有別的GTID EVENT,重啓後的Retrieved_Gtid_set可能相似1-3:5-6,中間產生Gap。
 
解決:
先加入到Retrieved_Gtid_Set,再寫Gtid Event到relay log中。若是寫入文件失敗了,則從集合中移除。
 
補丁:
 
 
問題描述:
主要有兩個問題:1. CREATE VIEW即時發生錯誤,也被記錄到binlog中;2. (1)產生的日誌在備庫上,即時被設置了過濾,也會將他的錯誤碼和當前錯誤碼相對比,這屬於設計邏輯錯誤。(Bug #76493, Bug #20797764)
 
解決:
對於第一個問題,不記錄binlog; 對於第二個問題,只有在event不被過濾的狀況下,才和本地作對比。
 
補丁:
 
 
問題描述:
在master_info_repository 或者relay_log_info_repository爲TABLE模式時,若是在一個開啓的事務中修改併發線程數,就可能致使實例直接crash,具體參閱咱們以前的月報分析:http://mysql.taobao.org/monthly/2015/10/05/
 
(Bug #74950, Bug #20074353)
 
解決:
禁止在活躍事務中修改上述兩個參數。
 
補丁:
 
 
問題描述:
在GTID開啓的狀況下,當master上 –binlog_checksum=none  , slave上配置爲binlog_checksum=crc32, 重啓Slave的SQL線程會報Event crc check錯誤。
 
一個relay log頭一般的序列以下:
Format_desc (of slave)
Previous-GTIDs (of slave)
Rotate (of master)
Format_desc (of master)
 
在SQL線程重啓時,調用Relay_log_info::init_relay_log_pos,須要找到從master上傳過來的FD事件,也就是第四個事件,然而,目前的邏輯認爲序列是這樣的:
Format_desc (of slave)
Rotate (of master)
Format_desc (of master)
 
按照上述序列,因爲邏輯上的錯誤,致使沒法找到正確的FD。(Bug #73806, Bug #20644100, Bug #76746, Bug #20909880)
 
解決:
須要忽略Previous-GTID和Rotate,找到正確的FD事件。
 
補丁:
 
 
問題描述:
前提:
1. relay-log-info-repository設置爲table模式
2. 打開GTID
3. 一個使用非事務引擎(例如MYISAM)的事務,被記錄到多個relay log時(在io線程寫relay log時,作個flush log操做)
 
在執行完上一個relay log時,前一個relay log被Purge,調用rli->flush_info(TRUE),會作一次隱式提交,致使gtid被消費,切換到下一個relay log,就會由於沒有gtid報錯。(Bug #68525, Bug #16418100)
 
解決:
當處於一個active的事務組時,不調用rli->flush_info。
 
補丁:
 
(Bug #68525, Bug #16418100)
相關文章
相關標籤/搜索