Master-slave+GTID架构下,从master导入5.6的备份,发现数据没有同步到从库,通过查看备份文件内容,发现sql_log_bin被设置为0从而在导入时禁用了binlog引起。
/*!40101 SET@OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET@OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
SET@MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
SET@@SESSION.SQL_LOG_BIN= 0;
-- GTID state atthe beginning of the backup
Mysqldump版本要求:5.6对应的mysqldump
那么很奇怪,mysqldump为何会莫名其妙地加上这几句命令呢,通过测试我发现
mysqldump -hXXXXXX -P3306 -uucloudbackup -pXXXXX--all-databases >/tmp/xx.sql
head -20/tmp/xx.sql
-- MySQL dump10.13.ucloudrel1 Distrib5.6.20-ucloudrel1, for Linux (x86_64)
--
-- Host: 10.9.160.127 Database:
--------------------------------------------------------
-- Serverversion 5.6.20-ucloudrel1-log
/*!40101 SET@OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET@OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET@OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SETNAMES utf8 */;
/*!40103 SET@OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SETTIME_ZONE='+00:00' */;
/*!40014 SET@OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS,FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET@OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET@OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
SET@MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
SET@@SESSION.SQL_LOG_BIN= 0;
mysqldump -hXXXXXX -P3306 -uucloudbackup –pXXXXX--all-databases --set-gtid-purged=OFF>/tmp/xx1.sql
head -20/tmp/xx1.sql
-- MySQL dump10.13.ucloudrel1 Distrib5.6.20-ucloudrel1, for Linux (x86_64)
--
-- Host: 10.9.160.127 Database:
--------------------------------------------------------
-- Serverversion 5.6.20-ucloudrel1-log
/*!40101 SET@OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET@OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET@OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SETNAMES utf8 */;
/*!40103 SET@OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SETTIME_ZONE='+00:00' */;
/*!40014 SET@OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS,FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET@OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET@OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- CurrentDatabase: `mysql`
假如在开了gtid复制的情况下,默认mysqldump会记录GTID_PURGED信息,但同时它还会引入一个其他动作,即输出以下几行
SET @MYSQLDUMP_TEMP_LOG_BIN= @@SESSION.SQL_LOG_BIN;
SET@@SESSION.SQL_LOG_BIN= 0;
假如mysqldump时设置了--set-gtid-purged=OFF,则在备份文件中不会打印有以上信息;
带着这样的困惑我去翻阅了下mysqldump客户端源码,发现了由函数set_session_binlog控制是否打印binlog信息
static voidset_session_binlog(my_bool flag)
{
static my_bool is_binlog_disabled= FALSE;
if (!flag && !is_binlog_disabled)
{
fprintf(md_result_file,
"SET @MYSQLDUMP_TEMP_LOG_BIN =@@SESSION.SQL_LOG_BIN;\n");
fprintf(md_result_file, "SET@@SESSION.SQL_LOG_BIN= 0;\n");
is_binlog_disabled= 1;
}
else if (flag && is_binlog_disabled)
{
fprintf(md_result_file,
"SET @@SESSION.SQL_LOG_BIN =@MYSQLDUMP_TEMP_LOG_BIN;\n");
is_binlog_disabled= 0;
}
}
从源码不难猜测:也就是说如果输入参数flag为0的话则会在mysqldump开始打印SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN等信息,调用后将is_binlog_disabled变量置为1,并在mysqldump结束时传入flag=1,打印SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN使得sql_log_bin参数恢复为原来的值。
通过函数process_set_gtid_purged来判断gtid信息
/**
This function processes theopt_set_gtid_purged option.
This function also calls set_session_binlog()function before
setting the SET @@GLOBAL.GTID_PURGED in theoutput.
@param[in] mysql_con the connection to the server
@retval FALSE successful according to the value
ofopt_set_gtid_purged.
@retval TRUE fail.
*/
if(gtid_mode_val && strcmp(gtid_mode_val, "OFF"))
{
/*
For any gtid_mode !=OFF and irrespectiveof --set-gtid-purged
being AUTO or ON, add GTID_PURGED in the output.
*/
if (opt_databases || !opt_alldbs ||!opt_dump_triggers
|| !opt_routines || !opt_events)
{
fprintf(stderr,"Warning: A partialdump from a server that has GTIDs will "
"by default includethe GTIDs of all transactions, even "
"those that changedsuppressed parts of the database. If "
"you don't want torestore GTIDs, pass "
"--set-gtid-purged=OFF. To make a complete dump, pass "
"--all-databases--triggers --routines --events. \n");
}
set_session_binlog(FALSE);
在main函数的部分可看到备份的末尾位置都会调用
/*
if --set-gtid-purged,restore binlog at the end of the session
if required.
*/
set_session_binlog(TRUE);
因为如果gtid打开的话,这时会走set_session_binlog函数的else分支,从而使sql_log_bin还原为初始值;如果gtid没有打开的话,is_binlog_disabled值必为0,则调用这个函数,实际上什么都没做。所以,dump结尾部分都会调用set_session_binlog(TRUE)
1 GTID+master-slave架构下,如果备份文件已经禁用了sql_log_bin,导入一个备份文件时需要将这几行去掉,总共三行
SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
SET @@SESSION.SQL_LOG_BIN= 0;
SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN;
2 分别导入两遍,master和slave同时导入