mysql 5.6的gtid_mode_[MySQL 5.6] GTID实现、运维变化及存在的bug
本文的主要目的是記下跟gtid相關的backtrace,用于以后的問題排查。另外也會討論目前在MySQL5.6.11版本中存在的bug。
前言:什么是GTID
什么是GTID呢, 簡而言之,就是全局事務ID(global transaction identifier ),最初由google實現(xiàn),官方MySQL在5.6才加入該功能,本文的起因在于5.6引入一大堆的gtid相關變量,深感困惑。
去年年中的時候,也寫過一片簡短的博客,大致介紹了下gtid是什么,http://mysqllover.com/?p=87。本文也不打算太多文字的介紹,因為網(wǎng)絡上已經(jīng)有大量的類似文章。
GTID的格式類似于:
7a07cd08-ac1b-11e2-9fcf-0010184e9e08:1
這是在我的一臺服務器上生成的gtid記錄,它在binlog中表現(xiàn)的事件類型就是:
GTID_LOG_EVENT:用于表示隨后的事務的GTID
另外還有兩種類型的GTID事件:
ANONYMOUS_GTID_LOG_EVENT :匿名GTID事件類型(暫且不論)
PREVIOUS_GTIDS_LOG_EVENT: 用于表示當前binlog文件之前已經(jīng)執(zhí)行過的GTID集合,記錄在Binlog文件頭,例如:
# at 120#130502 23:23:27 server id 119821? end_log_pos 231 CRC32 0x4f33bb48???? Previous-GTIDs# 10a27632-a909-11e2-8bc7-0010184e9e08:1,# 7a07cd08-ac1b-11e2-9fcf-0010184e9e08:1-1129
這個字符串,用“:”分開,前面表示這個服務器的server_uuid,這是一個128位的隨機字符串,在第一次啟動時生成(函數(shù)generate_server_uuid),對應的variables是只讀變量server_uuid。 它能以極高的概率保證全局唯一性,并存到文件DATA/auto.cnf中。因此要注意保護這個文件不要被刪除或修改,不然就麻煩了。
第二部分是一個自增的事務ID號,事務id號+server_uuid來唯一標示一個事務。
除了單獨的GTID外,還有一個GTID SET的概念。一個GTID SET的表示類似于:
7a07cd08-ac1b-11e2-9fcf-0010184e9e08:1-31
GTID_EXECUTED和GTID_PURGED是典型的GTID SET類型變量;在一個復制拓撲中,GTID_EXECUTED 可能包含好幾組數(shù)據(jù),例如:
mysql> show global variables like ‘%gtid_executed%’\G
*************************** 1. row ***************************
Variable_name: gtid_executed
Value: 10a27632-a909-11e2-8bc7-0010184e9e08:1-4,
153c0406-a909-11e2-8bc7-0010184e9e08:1-3,
7a07cd08-ac1b-11e2-9fcf-0010184e9e08:1-31,
f914fb74-a908-11e2-8bc6-0010184e9e08:1
本文討論的內(nèi)容包括:
一.主庫上的gtid產(chǎn)生及記錄
二.備庫如何使用GTID復制
三.主備運維的變化
四.MySQL5.6.11存在的bug
一、主庫上的Gtid
a.相關變量
主庫上每個事務的Gtid包括變化的部分和不變的部分。在討論之前,要弄清楚GTID維護的四個變量:
GTID_PURGED:已經(jīng)被刪除的binlog的事務,它是GTID_EXECUTED的子集,從MySQL5.6.9開始,該變量無法被設置。
GTID_OWNED:??表示正在執(zhí)行的事務的gtid以及對應的線程ID。
例如如下:
mysql> show global variables like ‘%gtid_owned%’\G
*************************** 1. row ***************************
Variable_name: gtid_owned
Value: 7a07cd08-ac1b-11e2-9fcf-0010184e9e08:11560057#67:11560038#89:11560059#7:11560034#32:11560053#56:11560052#112:11560055#128:11560054#65:11559997#96:11560056#90:11560051#85:11560058#39:11560061#12:11560060#125:11560035#62:11560062#5
1 row in set (0.01 sec)
GTID_EXECUTED表示已經(jīng)在該實例上執(zhí)行過的事務; 執(zhí)行RESET MASTER 會將該變量置空; 我們還可以通過設置GTID_NEXT執(zhí)行一個空事務,來影響GTID_EXECUTED
GTID_NEXT是SESSION級別變量,表示下一個將被使用的GTID
在內(nèi)存中也維護了與GTID_PURGED, GTID_OWNED, GTID_EXECUTED相對應的全局對象gtid_state。
gtid_state中維護了三個集合,其中l(wèi)ogged_gtids對應GTID_EXECUTED,?lost_gtids對應GTID_PURGED,owned_gtids對應GTID_OWNED
b.如何分配和使用GTID
在主庫執(zhí)行一個事務的過程中,關于Gtid主要涉及到以下幾個部分:
事務開始,執(zhí)行第一條SQL時,在寫入第一個“BEGIN” 的QUERY EVENT 之前, 為binlog cache 的Group_cache中分配一個group(Group_cache::add_logged_group),并寫入一個Gtid_log_event,此時并未為其分配事務id,backtrace 如下:
handler::ha_write_row->binlog_log_row->write_locked_table_maps->THD::binlog_write_table_map->binlog_start_trans_and_stmt->binlog_cache_data::write_event->Group_cache::add_logged_group
暫時還不清楚什么時候一個事務里會有多個gtid的group_cache.
在binlog group commit的flush階段:
第一步,調(diào)用Group_cache::generate_automatic_gno來為當前線程生成一個gtid,分配給thd->owned_gtid,并加入到owned_gtids中,backtrace如下:
MYSQL_BIN_LOG::process_flush_stage_queue->MYSQL_BIN_LOG::flush_thread_caches->binlog_cache_mngr::flush->binlog_cache_data::flush->gtid_before_write_cache->Group_cache::generate_automatic_gno->Gtid_state::acquire_ownership->Owned_gtids::add_gtid_owner
也就是說,直到事務完成,準備把binlog刷到binlog cache時,才會去為其分配gtid.
當gtid_next的類型為AUTOMATIC時,調(diào)用generate_automatic_gno生成事務id(gno),分配流程大概如下:
1.gtid_state->lock_sidno(automatic_gtid.sidno) , 為當前sidno加鎖,分配過程互斥
2.gtid_state->get_automatic_gno(automatic_gtid.sidno); 獲取事務ID
|–>初始化候選(candidate)gno為1
|–>從logged_gtids[$sidno]中掃描,獲取每個gno區(qū)間(iv):
|–>當candidate < iv->start(或者MAX_GNO,如果iv為NULL)時,判斷candidate是否有被占用,如果沒有的話,則使用該candidate,從函數(shù)返回,否則candidate++,繼續(xù)本步驟
|–>將candidate設置為iv->end,iv指向下一個區(qū)間,繼續(xù)第二步
從該過程可以看出,這里兼顧了區(qū)間存在碎片的場景,有可能分配的gno并不是全局最大的gno. 不過在主庫不手動設置gtid_next的情況下,我們可以認為主庫上的gno總是遞增的。
3.gtid_state->acquire_ownership(thd, automatic_gtid);
|–>加入到owned_gtids集合中(owned_gtids.add_gtid_owner),并賦值給thd->owned_gtid= gtid
4.gtid_state->unlock_sidno(automatic_gtid.sidno); ?解鎖
第二步, 調(diào)用Gtid_state::update_on_flush將當前事務的grid加入到logged_gtids中,backtrace如下:
MYSQL_BIN_LOG::process_flush_stage_queue->MYSQL_BIN_LOG::flush_thread_caches->binlog_cache_mngr::flush->binlog_cache_data::flush->MYSQL_BIN_LOG::write_cache->Gtid_state::update_on_flush
在bin log group commit的commit階段
調(diào)用Gtid_state::update_owned_gtids_impl 從owned_gtids中將當前事務的gtid移除,backtrace 如下:
MYSQL_BIN_LOG::ordered_commit->MYSQL_BIN_LOG::finish_commit->Gtid_state::update_owned_gtids_impl
上述步驟涉及到的是對logged_gtids和owned_gtids的修改。而lost_gtids除了啟動時維護外,就是在執(zhí)行Purge操作時維護。
例如,當我們執(zhí)行purge binary logs to ‘mysql-bin.000205′ 時, mysql-bin.index先被更新掉,然后再根據(jù)index文件找到第一個binlog文件的PREVIOUS_GTIDS_LOG_EVENT事件,更新lost_gtids集合,backtrace如下:
purge_master_logs->MYSQL_BIN_LOG::purge_logs->MYSQL_BIN_LOG::init_gtid_sets->read_gtids_from_binlog->Previous_gtids_log_event::add_to_set->Gtid_set::add_gtid_encoding->Gtid_set::add_gno_interval
關于binlog group commit,參見之前寫的博客:
c.如何持久化GTID
當重啟MySQL后,我們看到GTID_EXECUTED和GTID_PURGED和重啟前是一致的。
持久化GTID,是通過全局對象gtid_state來管理的。gtid_state在系統(tǒng)啟動時調(diào)用函數(shù)gtid_server_init分配內(nèi)存;如果打開了binlog,則會做進一步的初始化工作:
quoted code:
5419?????? if (mysql_bin_log.init_gtid_sets(
5420???????????? const_cast(gtid_state->get_logged_gtids()),
5421???????????? const_cast(gtid_state->get_lost_gtids()),
5422???????????? opt_master_verify_checksum,
5423???????????? true/*true=need lock*/))
5424???????? unireg_abort(1);
gtid_state 包含3個gtid集合:logged_gtids,?lost_gtids,?owned_gtids,前兩個都是gtid_set類型, owned_gtids類型為Owned_gtids
MYSQL_BIN_LOG::init_gtid_sets 主要用于初始化logged_gtids和lost_gtids,該函數(shù)的邏輯簡單描述下:
1.掃描mysql-index文件,搜集binlog文件名,并加入到filename_list中
2.從最后一個文件開始往前讀,依次調(diào)用函數(shù)read_gtids_from_binlog:
|–>打開binlog文件,如果讀取到PREVIOUS_GTIDS_LOG_EVENT事件
(1)無論如何,將其加入到logged_gtids(prev_gtids_ev->add_to_set(all_gtids))
(2)如果該文件是第一個binlog文件,將其加入到lost_gtids(prev_gtids_ev->add_to_set(prev_gtids))中.
|–>獲取GTID_LOG_EVENT事件
(1) 讀取該事件對應的sidno,sidno= gtid_ev->get_sidno(false);
這是一個32位的整型,用sidno來代表一個server_uuid,從1開始計算,這主要處于節(jié)省內(nèi)存的考慮。維護在全局對象global_sid_map中。
當sidno還沒加入到map時,調(diào)用global_sid_map->add_sid(sid),sidno從1開始遞增。
(2) all_gtids->ensure_sidno(sidno)
all_gtids是gtid_set類型,可以理解為一個集合,ensure_sidno就是要確保這個集合至少可以容納sidno個元素
(3) all_gtids->_add_gtid(sidno, gtid_ev->get_gno()
將該事件中記錄的gtid加到all_gtids[sidno]中(最終調(diào)用Gtid_set::add_gno_interval,這里實際上是把(gno, gno+1)這樣一個區(qū)間加入到其中,這里
面涉及到區(qū)間合并,交集等操作 ? ?)
當?shù)谝粋€文件中既沒有PREVIOUS_GTIDS_LOG_EVENT, 也沒有GTID_LOG_EVENT時,就繼續(xù)讀上一個文件
如果只存在PREVIOUS_GTIDS_LOG_EVENT事件,函數(shù)read_gtids_from_binlog返回GOT_PREVIOUS_GTIDS
如果還存在GTID_LOG_EVENT事件,返回GOT_GTIDS
這里很顯然存在一個問題,即如果在重啟前,我們并沒有使用gtid_mode,并且產(chǎn)生了大量的binlog,在這次重啟后,我們就可能需要掃描大量的binlog文件。這是一個非常明顯的Bug, 后面再集中討論。
3.如果第二部掃描,沒有到達第一個文件,那么就從第一個文件開始掃描,和第2步流程類似,讀取到第一個PREVIOUS_GTIDS_LOG_EVENT事件,并加入到lost_gtids中。
簡單的講,如果我們一直打開的gtid_mode,那么只需要讀取第一個binlog文件和最后一個binlog文件,就可以確定logged_gtids和lost_gtids這兩個GTID SET了。
二、備庫上的GTID
a.如何保持主備GTID一致
由于在binlog中記錄了每個事務的GTID,因此備庫的復制線程可以通過設置線程級別GTID_NEXT來保證主庫和備庫的GTID一致。
默認情況下,主庫上的thd->variables.gtid_next.type為AUTOMATIC_GROUP,而備庫為GTID_GROUP
備庫SQL線程gtid_next輸出:
(gdb) p thd->variables.gtid_next$2 = {type = GTID_GROUP,gtid = {sidno = 2,gno = 1127,static MAX_TEXT_LENGTH = 56},static MAX_TEXT_LENGTH = 56}
C/C++ 中的 gdb 也是一個類似的命令行 debugger,只是用來調(diào)試 C/C++ 而已,使用的模式跟Python的pdb/ipdb相似,具體可參考 用GDB調(diào)試程序。
這些變量在執(zhí)行Gtid_log_event時被賦值:Gtid_log_event::do_apply_event,大體流程為:
1.rpl_sidno sidno= get_sidno(true); ?獲取sidno
2.thd->variables.gtid_next.set(sidno, spec.gtid.gno); ?設置gtid_next
3.gtid_acquire_ownership_single(thd);
|–>檢查該gtid是否在logged_gtids集合中,如果在的話,則返回(gtid_pre_statement_checks會忽略該事務)
|–>如果該gtid已經(jīng)被其他線程擁有,則等待(gtid_state->wait_for_gtid(thd, gtid_next)),否則將當前線程設置為owner(gtid_state->acquire_ownership(thd, gtid_next))
在上面提到,有可能當前事務的GTID已經(jīng)在logged_gtids中,因此在執(zhí)行Rows_log_event::do_apply_event或者mysql_execute_command函數(shù)中,都會去調(diào)用函數(shù)gtid_pre_statement_checks
該函數(shù)也會在每個SQL執(zhí)行前,檢查gtid是否合法,主要流程包括:
1.當打開選項enforce_gtid_consistency時,檢查DDL是否被允許執(zhí)行(thd->is_ddl_gtid_compatible()),若不允許,返回GTID_STATEMENT_CANCEL
2.檢查當前SQL是否會產(chǎn)生隱式提交并且gtid_next被設置(gtid_next->type != AUTOMATIC_GROUP),如果是的話,則會拋出錯誤ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET 并返回GTID_STATEMENT_CANCEL,注意這里會導致bug#69045
3.對于BEGIN/COMMIT/ROLLBACK/(SET OPTION 或者 SELECT )且沒有使用存儲過程/ 這幾種類型的SQL,總是允許執(zhí)行,返回GTID_STATEMENT_EXECUTE
4.gtid_next->type為UNDEFINED_GROUP,拋出錯誤ER_GTID_NEXT_TYPE_UNDEFINED_GROUP,返回GTID_STATEMENT_CANCEL
5.gtid_next->type == GTID_GROUP且thd->owned_gtid.sidno == 0時, 返回GTID_STATEMENT_SKIP
其中第五步中處理了函數(shù)gtid_acquire_ownership_single的特殊情況
b.備庫如何發(fā)起DUMP請求
引入GTID,最大的好處當然是我們可以隨心所欲的切換主備拓撲結構了。在一個正常運行的復制結構中,我們可以在備庫簡單的執(zhí)行如下SQL:
CHANGE MASTER TO MASTER_USER=’$USERNAME’, MASTER_HOST=’ ‘, MASTER_PORT=’ ‘, MASTER_AUTO_POSITION=1;
打開GTID后,我們就無需指定binlog文件或者位置,MySQL會自動為我們做這些事情。這里的關鍵就是MASTER_AUTO_POSITION。IO線程連接主庫,可以大概分為以下幾步:
1.IO線程在和主庫建立TCP鏈接后,會去獲取主庫的uuid(get_master_uuid),然后在主庫上設置一個用戶變量@slave_uuid(io_thread_init_commands)
2.之后,在主庫上注冊SLAVE(register_slave_on_master)
在主庫上調(diào)用register_slave來注冊備庫,將備庫的host,user,password,port,server_id等信息記錄到slave_list哈希中。
3.調(diào)用request_dump,開始向主庫請求數(shù)據(jù),這里分兩種情況:
MASTER_AUTO_POSITION=0時,向主庫發(fā)送命令的類型為COM_BINLOG_DUMP,這是傳統(tǒng)的請求BINLOG的模式
MASTER_AUTO_POSITION=1時,命令類型為COM_BINLOG_DUMP_GTID,這是新的方式。
這里我們只討論第二種。第二種情況下,會先去讀取備庫已經(jīng)執(zhí)行的gtid集合
quoted code in rpl_slave.cc :
2974?? if (command == COM_BINLOG_DUMP_GTID)
2975?? {
2976???? // get set of GTIDs
2977???? Sid_map sid_map(NULL/*no lock needed*/);
2978???? Gtid_set gtid_executed(&sid_map);
2979???? global_sid_lock->wrlock();
2980???? gtid_state->dbug_print();
2981???? if (gtid_executed.add_gtid_set(mi->rli->get_gtid_set()) != RETURN_STATUS_OK ||
2982???????? gtid_executed.add_gtid_set(gtid_state->get_logged_gtids()) !=
2983???????? RETURN_STATUS_OK)
構建完成發(fā)送包后,發(fā)送給主庫。
在主庫上接受到命令后,調(diào)用入口函數(shù)com_binlog_dump_gtid,流程如下:
1.slave_gtid_executed.add_gtid_encoding(packet_position, data_size) ;讀取備庫傳來的GTID SET
2.讀取備庫的uuid(get_slave_uuid),被根據(jù)uuid來kill僵尸線程(kill_zombie_dump_threads)
這也是之前SLAVE IO線程執(zhí)行SET @SLAVE_UUID的用處。
3.進入mysql_binlog_send函數(shù):
|–>調(diào)用MYSQL_BIN_LOG::find_first_log_not_in_gtid_set,從最后一個Binlog開始掃描,獲取文件頭部的PREVIOUS_GTIDS_LOG_EVENT,如果它是slave_gtid_executed的子集,保存當前binlog文件名,否則繼續(xù)向前掃描。
這一步的目的就是為了找出備庫執(zhí)行到的最后一個Binlog文件。
|–>從這個文件頭部開始掃描,遇到GTID_EVENT時,會去判斷該GTID是否包含在slave_gtid_executed中:
Gtid_log_event gtid_ev(packet->ptr() + ev_offset,
packet->length() – checksum_size,
p_fdle);
skip_group= slave_gtid_executed->contains_gtid(gtid_ev.get_sidno(sid_map),
gtid_ev.get_gno());
主庫通過GTID決定是否可以忽略事務,從而決定執(zhí)行開始的位置
注意,在使用MASTER_LOG_POSITION后,就不要指定binlog的位置,否則會報錯。
三、運維操作
a.如何忽略復制錯誤
當備庫復制出錯時,傳統(tǒng)的跳過錯誤的方法是設置sql_slave_skip_counter,然后再START SLAVE。
但如果打開了GTID,就會設置失敗:
mysql> set global sql_slave_skip_counter = 1;
ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction
提示的錯誤信息告訴我們,可以通過生成一個空事務來跳過錯誤的事務。
我們手動產(chǎn)生一個備庫復制錯誤:
Last_SQL_Error: Error ‘Unknown table ‘test.t1” on query. Default database: ‘test’. Query: ‘DROP TABLE `t1` /* generated by server */’
查看binlog中,該DDL對應的GTID為7a07cd08-ac1b-11e2-9fcf-0010184e9e08:1131
在備庫上執(zhí)行:
mysql> STOP SLAVE;
Query OK, 0 rows affected (0.00 sec)
mysql> SET SESSION GTID_NEXT = ’7a07cd08-ac1b-11e2-9fcf-0010184e9e08:1131′;
Query OK, 0 rows affected (0.00 sec)
mysql> BEGIN; COMMIT;
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> SET SESSION GTID_NEXT = AUTOMATIC;
Query OK, 0 rows affected (0.00 sec)
mysql> START SLAVE;
再查看show slave status,就會發(fā)現(xiàn)錯誤事務已經(jīng)被跳過了。這種方法的原理很簡單,空事務產(chǎn)生的GTID加入到GTID_EXECUTED中,這相當于告訴備庫,這個GTID對應的事務已經(jīng)執(zhí)行了。
b.重指主庫
使用change master to …. , MASTER_AUTO_POSITION=1;
注意在整個復制拓撲中,都需要打開gtid_mode
c.新的until條件
5.6提供了新的util condition,可以根據(jù)GTID來決定備庫復制執(zhí)行到的位置
SQL_BEFORE_GTIDS:在指定的GTID之前停止復制
SQL_AFTER_GTIDS :在指定的GTID之后停止復制
判斷函數(shù)為Relay_log_info::is_until_satisfied
d.適當減小binlog文件的大小
如果開啟GTID,理論上最好調(diào)小每個binlog文件的最大值,以縮小掃描文件的時間。
四、存在的bug
bug#69097, 即使關閉了gtid_mode,也會在啟動時去掃描binlog文件。
當在重啟前沒有使用gtid_mode,重啟后可能會去掃描所有的binlog文件,如果Binlog文件很多的話,這顯然是不可接受的。
bug#69096,無法通過GTID_NEXT_LIST來跳過復制錯誤,因為默認編譯下,GTID_NEXT_LIST未被編譯進去。
TODO:GTID_NEXT_LIST的邏輯上面均未提到,有空再看。
bug#69095,將備庫的復制模式設置為STATEMENT/MIXED。 主庫設置為ROW模式,執(zhí)行DML 會導致備庫復制中斷
Last_SQL_Error: Error executing row event: ‘Cannot execute statement: impossible to write to binary log since statement is in row format and BINLOG_FORMAT = STATEMENT.’
判斷報錯的backtrace:
handle_slave_worker->slave_worker_exec_job->Rows_log_event::do_apply_event->open_and_lock_tables->open_and_lock_tables->lock_tables->THD::decide_logging_format
解決辦法:將備庫的復制模式設置為’ROW’ ,保持主備一致
該bug和GTID無關
bug#69045, 當主庫執(zhí)行類似 FLUSH PRIVILEGES這樣的動作時,如果主庫和備庫都開啟了gtid_mode,會導致復制中斷
Last_SQL_Error: Error ‘Cannot execute statements with implicit commit inside a transaction when @@SESSION.GTID_NEXT != AUTOMATIC or @@SESSION.GTID_NEXT_LIST != NULL.’ on query. Default database: ”. Query: ‘flush privileges’
也是一個很低級的bug,在MySQL5.6.11版本中,如果有可能導致隱式提交的事務, 則gtid_next必須等于AUTOMATIC,對備庫復制線程而言,很容易就中斷了,判斷邏輯在函數(shù)gtid_pre_statement_checks中
參考文檔
1.阿里長源的三篇博客(一,?二, 三)
2.MySQL5.6.11源代碼
http://mysql.taobao.org/monthly/2020/05/09/
GTID的生成和使用由以下幾步組成:
主服務器更新數(shù)據(jù)時,會在事務前產(chǎn)生GTID,一同記錄到binlog日志中。
binlog傳送到從服務器后,被寫入到本地的relay log中。從服務器讀取GTID,并將其設定為自己的GTID(GTID_NEXT系統(tǒng))。
sql線程從relay log中獲取GTID,然后對比從服務器端的binlog是否有記錄。
如果有記錄,說明該GTID的事務已經(jīng)執(zhí)行,從服務器會忽略。
如果沒有記錄,從服務器就會從relay log中執(zhí)行該GTID的事務,并記錄到binlog。
GTID_OWNED:
表示正在執(zhí)行的事務的GTID以及其對應的線程ID。
Scope : Global, Session
Dynamic : No
Type : String
如果GDIT_OWNED是全局變量,它包含所有當前服務器上正在使用的GTIDs和使用它們的線程IDs。這個變量主要用于并行復制,從而可以查看一個事務是否已經(jīng)被另一個線程處理。這個線程會擁有所處理事務的ownership。@@global.grid_owned會顯示出GTID和它的owner。當事務處理完成,線程會釋放ownership. 如果GDIT_OWNED是session變量,它包含一個seesion正在使用的GTID。這個變量對測試和debug會很有幫助
gtid在各個mysql節(jié)點的binlog里面都是全局唯一
f
總結
以上是生活随笔為你收集整理的mysql 5.6的gtid_mode_[MySQL 5.6] GTID实现、运维变化及存在的bug的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux下的gpio转串口驱动,X-0
- 下一篇: 如何卸载mysql server 200