怎么理解从库的IO线程
发布时间:2021-12-23 10:48:09 所属栏目:MySql教程 来源:互联网
导读:本篇内容介绍了怎么理解从库的IO线程的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 一、流程解析 start_slave -start_slave_threads - if (!mi-inite
本篇内容介绍了“怎么理解从库的IO线程”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!![]() 一、流程解析 start_slave ->start_slave_threads -> if (!mi->inited || !mi->rli->inited)//如果没有初始化 { int error= (!mi->inited ? ER_SLAVE_MI_INIT_REPOSITORY : ER_SLAVE_RLI_INIT_REPOSITORY); ER_SLAVE_MI_INIT_REPOSITORY ER_SLAVE_RLI_INIT_REPOSITORY -> if (mi->is_auto_position() && (thread_mask & SLAVE_IO) && get_gtid_mode(GTID_MODE_LOCK_NONE) == GTID_MODE_OFF) ER_CANT_USE_AUTO_POSITION_WITH_GTID_MODE_OFF eng "The replication receiver thread%-.192s cannot start in AUTO_POSITION mode: this server uses @@GLOBAL.GTID_MODE = OFF." -> 启动IO 线程 if (thread_mask & SLAVE_IO) is_error= start_slave_thread( #ifdef HAVE_PSI_INTERFACE key_thread_slave_io, #endif handle_slave_io, lock_io, lock_cond_io, cond_io, &mi->slave_running, &mi->slave_run_id, mi); -> mysql_thread_create 建立线程 回调函数handle_slave_io ->handle_slave_io ->初始化IO线程属性 init_slave_thread 进入状态THD_STAGE_INFO(thd, stage_waiting_for_master_update); ->safe_connect 进行连接主库 ->connect_to_master ->将参数slave_net_timeout设置为IO线程连接超时和IO线程读取Event 超时 case MYSQL_OPT_CONNECT_TIMEOUT: //MYSQL_OPT_CONNECT_TIMEOUT mysql->options.connect_timeout= *(uint*) arg; break; case MYSQL_OPT_READ_TIMEOUT://MYSQL_OPT_READ_TIMEOUT mysql->options.read_timeout= *(uint*) arg; break; ->循环 实现连接和重新连接 -> 根据用户名、密码、IP、端口建立连接 mysql_real_connect(mysql, mi->host, user, password, 0, mi->port, 0, client_flag) ->如果连接失败 循环重连 每次打印日志 mi->report(ERROR_LEVEL, last_errno, "error %s to master '%s@%s:%d'" " - retry-time: %d retries: %lu", (reconnect ? "reconnecting" : "connecting"), mi->get_user(), mi->host, mi->port, mi->connect_retry, err_count + 1); if (++err_count == mi->retry_count) { slave_was_killed=1; break; } slave_sleep(thd, mi->connect_retry, io_slave_killed, mi); //睡眠时间 每次睡眠时间为MASTER_CONNECT_RETRY设置的时间,默认60秒,循环次数由MASTER_RETRY_COUNT指定 默认86400次 ->get_master_version_and_clock ->比较版本 ->发起命令SELECT UNIX_TIMESTAMP() 获取主库时间 mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP() 计算差值用于延迟计算 mi->clock_diff_with_master= (long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10)); 也就是说差值计算是在start slave命令发起的时候进行计算的,后面如果修改slave的服务器时间 那么延迟计算将出现问题 ->发起命令SELECT @@GLOBAL.SERVER_ID 获取主库server id 比较主库的server id和本从库是否相同,如果相同则报错 The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it). ->发起命令SELECT @@GLOBAL.COLLATION_SERVER 如果主库的这个值和备库不一致将会报错 The slave I/O thread stops because master and slave have different values for the COLLATION_SERVER global variable. The values must be equal for the Statement-format replication to work ->发起命令SELECT @@GLOBAL.TIME_ZONE 老版本检测 比较主库和从库的时区,如果不一致 The slave I/O thread stops because master and slave have different values for the TIME_ZONE global variable. The values must be equal for the Statement-format replication to work ->发起命令SELECT @@GLOBAL.GTID_MODE 比较主库和从库的GTID MODE是否兼容 if ((slave_gtid_mode == GTID_MODE_OFF && master_gtid_mode >= GTID_MODE_ON_PERMISSIVE) || (slave_gtid_mode == GTID_MODE_ON && master_gtid_mode <= GTID_MODE_OFF_PERMISSIVE)) { mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, "The replication receiver thread cannot start because " "the master has GTID_MODE = %.192s and this server has " "GTID_MODE = %.192s.", get_gtid_mode_string(master_gtid_mode), get_gtid_mode_string(slave_gtid_mode)); DBUG_RETURN(1); } if (mi->is_auto_position() && master_gtid_mode != GTID_MODE_ON) { mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, "The replication receiver thread cannot start in " "AUTO_POSITION mode: the master has GTID_MODE = %.192s " "instead of ON.", get_gtid_mode_string(master_gtid_mode)); DBUG_RETURN(1); } ->回到handle_slave_io ->get_master_uuid 获取主句UUID 比较UUID 发起命令SELECT @@GLOBAL.SERVER_UUID 比较主库和备库的UUID如果相同报错 "The slave I/O thread stops because master and slave have equal " "MySQL server UUIDs; these UUIDs must be different for " "replication to work." ->io_thread_init_commands SET @slave_uuid= '%s' 是什么意思 ->register_slave_on_master 进行注册 主库调用register_slave进行注册 注册完成后 show slave hosts就能查询到了 主库show slave会调用 show_slave_hosts 函数 ->request_dump 发送需要读取的GTID或者位点信息给主库。 如果是AUTO com_binlog_dump_gtid - restirve_gtid+execute_gtid if (gtid_executed.add_gtid_set(mi->rli->get_gtid_set()) != RETURN_STATUS_OK || gtid_executed.add_gtid_set(gtid_state->get_executed_gtids()) != RETURN_STATUS_OK) - server_id 主库读取 (gdb) p gtid_string $17 = 0x7ffee400ef20 "010fde77-2075-11e9-ba07-5254009862c0:1,ncb7ea36e-670f-11e9-b483-5254008138e4:1-16" (gdb) p name $18 = ' |