天天看點

MySQL核心月報 2014.12-MySQL· 踩過的坑·5.6 GTID 和存儲引擎那會事

<b>混用引擎的問題</b>

我們下面舉例子來說明,t1_i 是事務引擎表(innodb),ti_m 是非事務引擎(myisam)。

在事務執行前2張表裡的資料如下:

事務如下,對2張表分别插一條資料,然後 rollback 模拟出錯復原,

執行復原後,我們會看到 mysql 傳回資訊中有 warnings;

query ok, 0 rows affected, 1 warning

檢視 warning,可以清楚地看到提示,非事務引擎無法復原:

我們來看下現在2張表中的資料,可以看到 t1_m 的插入确實沒有復原,這與事務邏輯的預期是不一樣的。

當我們在非事務引擎上執行事務相關的操作的時候,mysql 一般是不會報錯的,比如在非事務引擎的操作前後用 begin 和 commit, 這是完全可以的,并且讓我們誤以為操作是有事務性的,我們在使用的時候要注意這一點。

總的來說,要遵循這樣的一條原則,不要在事務中混用不同的存儲引擎。

<b>5.5 到 5.6 更新問題</b>

5.5 更新到 5.6 的時候,我們會先建立一個5.6版本的執行個體,然後把資料從5.5遷移到5.6,最後把連接配接切到 5.6 完成更新。有時候更新會失敗,這是因為5.6 gtid 的一些限制導緻的。

其中有一條是關于臨時表的限制,官方描述如下:

temporary tables. create temporary table and drop temporary table statements are not supported inside transactions when using gtids (that is, when the server was started with the --enforce-gtid-consistency option). it is possible to use these statements with gtids enabled, but only outside of any transaction, and only with autocommit=1.

限制表明不能在事務中建立臨時表,可以在事務外建立,但要求 autocommit = 1。

我們建立5.6的執行個體的時候,會重用 5.5 的配置,autocommit 就是其中之一,并且這個是允許使用者配置的,如果使用者在5.5執行個體上把這個值改為0,然後更新到5.6,就會出錯。我們知道,建立新執行個體的時候,會先通過 mysql_install_db 腳本初始化資料庫,這包括系統表的建立、基本資料的添加等 ,其中會用到 mysql_system_tables_data.sql 這個sql腳本,裡面有:

create temporary table tmp_db like db;  create temporary table tmp_user like user;  create temporary table tmp_proxies_priv like proxies_priv; 

這樣的語句,腳本執行失敗,是以mysql.db 、mysql.user 和 mysql.proxies_priv表裡的初始資料就沒有添加進去。

error log 中會看到這樣的資訊

2014-12-08 20:48:15 9264 [warning] bootstrap mode disables gtids. bootstrap mode should only be used by mysql_install_db which initializes the mysql data directory and creates system tables. error: 1787 when @@global.enforce_gtid_consistency = 1, the statements create temporary table and drop temporary table can be executed in a non-transactional context only, and require that autocommit = 1. 2014-12-08 20:48:16 9264 [error] aborting

我們這時如果正常啟動mysqld的話,會發現預設root使用者是登入不進去的,因為user表是空的,根本沒有root使用者,而匿名使用者 @localhost 又什麼也做不了。

我們用 --skip-grant-tables 啟動資料庫後,匿名使用者登入進去,檢視user表,會發現是空的。

因為建立的資料庫不可用,是以最終導緻遷移失敗。

這個問題的根本原因是5.5的配置檔案中 autocommit = 0 導緻的,是以好的解決方法是我們在更新5.6前,把這個值設定為1,然後再更新。