ESP32 BLE连接老是断?手把手教你优化连接稳定性与功耗(附完整代码)
2026/4/22 5:23:45
MySQL 版本: 8.0.26
| 对比项 | MGR 集群 (mysql-65cbddad) | 主备集群 (mysql-a486e45d) |
|---|---|---|
| 集群策略 | MGRCluster | MySQLRWCluster |
| 数据库版本 | mysql8.0.26-mgr | mysql8.0.26 |
| 节点数量 | 3节点 (1主2备) | 2节点 (1主1备) |
| 部署模式 | 多主模式 (单主写入) | 传统主从复制 |
MGR 集群: event_scheduler = OFF 主备集群: event_scheduler = OFF# /etc/mysql/my.cnf [mysqld] event_scheduler=0event_scheduler 默认关闭原因:
启用方式:
-- 方式1: 动态开启 (仅主节点)SETGLOBALevent_scheduler=ON;-- 方式2: 在配置文件中开启 (需重启)-- 修改 /etc/mysql/my.cnfevent_scheduler=1最佳实践:
| 配置项 | MGR 集群 | 主备集群 | 说明 |
|---|---|---|---|
binlog_format | ROW | ROW | 行级复制,MGR强制要求 |
gtid_mode | ON | ON | 使用GTID全局事务ID |
enforce_gtid_consistency | ON | ON | 强制GTID一致性 |
log_slave_updates | ON | ON | 从库记录中继日志到binlog |
binlog_row_image | FULL | FULL | 记录完整行镜像 |
slave_parallel_type | LOGICAL_CLOCK | LOGICAL_CLOCK | 并行复制类型 |
slave_parallel_workers | 16 | 16 | 并行复制线程数 |
slave_preserve_commit_order | ON | ON | 保持事务提交顺序 |
| 配置��� | MGR 集群 | 主备集群 | 说明 |
|---|---|---|---|
| 复制机制 | Group Replication | Binlog半同步复制 | 核心差异 |
| group_replication_group_seeds | mysql-65cbddad00-headless:33061,… | 无 | MGR组成员发现 |
| transaction_write_set_extraction | XXHASH64 | XXHASH64 | 写集提取算法 |
| 半同步复制 | 不使用 | 使用 rpl_semi_sync_master | 主备专用 |
文件:/etc/mysql.cnf.d/mgr_group.cnf
[mysqld] report_host='245.0.4.201' loose-group_replication_local_address='245.0.4.201:33061' loose-group_replication_group_seeds='mysql-65cbddad00-headless:33061,...' loose-group_replication_gtid_assignment_block_size=1文件:/etc/mysql/ext.semi.cnf
# 半同步复制插件 loose-rpl_semi_sync_master_enabled=1 loose-rpl_semi_sync_master_timeout=1000 loose-rpl_semi_sync_master_wait_no_slave=OFF loose-rpl_semi_sync_master_wait_for_slave_count=1 loose-rpl_semi_sync_master_wait_point=AFTER_SYNC loose-rpl_semi_sync_slave_enabled=1| 对象类型 | 同步机制 | 说明 |
|---|---|---|
| 存储过程 | 通过 binlog DDL 语句同步 | CREATE/ALTER PROCEDURE 记录在binlog |
| 触发器 | 通过 binlog DDL 语句同步 | CREATE TRIGGER 记录在binlog |
| 定时器 | 通过 binlog DDL 语句同步 | CREATE EVENT 记录在binlog |
| 执行 | event_scheduler 控制执行 | 语法自动同步,执行需调度器 |
log_bin_trust_function_creators
MGR 集群: log_bin_trust_function_creators = OFF 主备集群: log_bin_trust_function_creators = OFF 配置文件中: log_bin_trust_function_creators=1 (实际已启用)此参数控制是否信任存储函数创建者:
OFF: 创建存储函数/触发器需要 SUPER 权限或 DETERMINISTIC/NO SQL 声明ON: 允许创建任意存储函数-- 1. 查看存储过程SELECTROUTINE_NAME,ROUTINE_TYPEFROMinformation_schema.ROUTINESWHEREROUTINE_SCHEMA='your_db';-- 2. 查看触发器SELECTTRIGGER_NAME,EVENT_MANIPULATIONFROMinformation_schema.TRIGGERSWHERETRIGGER_SCHEMA='your_db';-- 3. 查看事件/定时器SELECTEVENT_NAME,STATUS,EXECUTE_ATFROMinformation_schema.EVENTSWHEREEVENT_SCHEMA='your_db';-- 在主节点 (PRIMARY/Master) 执行USEtest_db;-- 删除已存在的存储过程(幂等性设计)DROPPROCEDUREIFEXISTSsp_sample_process;-- 创建存储过程DELIMITER//CREATEPROCEDUREsp_sample_process()DETERMINISTICREADSSQLDATABEGINSELECTCOUNT(*)AStable_countFROMinformation_schema.TABLESWHERETABLE_SCHEMA='test_db';END//DELIMITER;-- 验证创建成功SHOWPROCEDURESTATUSWHEREDb='test_db'ANDName='sp_sample_process';# 1. 获取 GTID 位置(主节点)kubectlexec-it -n qfusion-admin<primary-pod>-c mysql -- mysql -u root -p -e" SELECT @@GLOBAL.GTID_EXECUTED; "# 2. 检查从节点 GTID 是否一致kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p -e" SELECT @@GLOBAL.GTID_EXECUTED; SHOW SLAVE STATUS\G "# 3. 在从节点验证存储过程已同步kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p -e" SELECT ROUTINE_NAME, ROUTINE_TYPE, CREATED FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = 'test_db' AND ROUTINE_NAME = 'sp_sample_process'; "# 4. 查看存储过程定义(确认代码一致)kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p -e" SHOW CREATE PROCEDURE test_db.sp_sample_process\G "| 检查项 | 命令 | 预期结果 |
|---|---|---|
| 主节点 GTID | SELECT @@GLOBAL.GTID_EXECUTED; | 返回 GTID 集合 |
| 从节点同步状态 | SHOW SLAVE STATUS\G | Seconds_Behind_Master: 0 |
| 从节点 GTID | SELECT @@GLOBAL.GTID_EXECUTED; | 与主节点一致 |
| 存储过程存在 | SHOW PROCEDURE STATUS | 能查到 sp_sample_process |
| 存储过程代码 | SHOW CREATE PROCEDURE | 代码与主节点一致 |
-- 在主节点 (PRIMARY/Master) 执行USEtest_db;-- 创建测试表DROPTABLEIFEXISTSt_audit_log;CREATETABLEt_audit_log(idBIGINTAUTO_INCREMENTPRIMARYKEY,table_nameVARCHAR(64),actionVARCHAR(16),old_value JSON,new_value JSON,created_atTIMESTAMPDEFAULTCURRENT_TIMESTAMP);DROPTABLEIFEXISTSt_users;CREATETABLEt_users(idINTAUTO_INCREMENTPRIMARYKEY,usernameVARCHAR(50),emailVARCHAR(100),updated_atTIMESTAMPDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP);-- 删除已存在的触发器DROPTRIGGERIFEXISTStr_users_after_update;-- 创建触发器(记录更新操作)DELIMITER//CREATETRIGGERtr_users_after_updateAFTERUPDATEONt_usersFOR EACH ROWBEGININSERTINTOt_audit_log(table_name,action,old_value,new_value)VALUES('t_users','UPDATE',JSON_OBJECT('id',OLD.id,'username',OLD.username,'email',OLD.email),JSON_OBJECT('id',NEW.id,'username',NEW.username,'email',NEW.email));END//DELIMITER;-- 验证创建成功SHOWTRIGGERSLIKE't_users';# 1. 在主节点测试触发器kubectlexec-it -n qfusion-admin<primary-pod>-c mysql -- mysql -u root -p test_db -e" INSERT INTO t_users (username, email) VALUES ('user1', 'user1@test.com'); UPDATE t_users SET email = 'newemail@test.com' WHERE username = 'user1'; SELECT * FROM t_audit_log ORDER BY id DESC LIMIT 1; "# 2. 检查从节点同步状态kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p -e" SHOW SLAVE STATUS\G "|grep-E"Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master"# 3. 在从节点验证触发器定义已同步kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p -e" SELECT TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE, ACTION_TIMING FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'test_db' AND TRIGGER_NAME = 'tr_users_after_update'; "# 4. 查看触发器详细定义kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p -e" SHOW CREATE TRIGGER test_db.tr_users_after_update\G "# 5. 验证数据已同步(注意:从节点不会再次执行触发器)kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p test_db -e" SELECT * FROM t_users; SELECT * FROM t_audit_log; "| 检查项 | 命令 | 预期结果 |
|---|---|---|
| 触发器定义同步 | SHOW TRIGGERS LIKE 't_users' | 能查到 tr_users_after_update |
| 触发器详情 | SHOW CREATE TRIGGER | 定义与主节点一致 |
| 数据表同步 | SELECT * FROM t_users | 数据一致 |
| 审计日志同步 | SELECT * FROM t_audit_log | 主节点执行结果已同步 |
-- 在主节点 (PRIMARY/Master) 执行USEtest_db;-- 先启用事件调度器(仅主节点)SETGLOBALevent_scheduler=ON;-- 验证调度器已启动SHOWVARIABLESLIKE'event_scheduler';-- 删除已存在的事件DROPEVENTIFEXISTSev_cleanup_old_logs;-- 创建定时清理任务(每分钟执行一次)DELIMITER//CREATEEVENT ev_cleanup_old_logsONSCHEDULE EVERY1MINUTESTARTSCURRENT_TIMESTAMPDOBEGINDECLARErows_deletedINTDEFAULT0;-- 清理30天前的审计日志DELETEFROMt_audit_logWHEREcreated_at<DATE_SUB(NOW(),INTERVAL30DAY)LIMIT1000;SETrows_deleted=ROW_COUNT();-- 记录执行日志(可选)INSERTINTOt_audit_log(table_name,action,new_value)VALUES('event_scheduler','cleanup',JSON_OBJECT('deleted_rows',rows_deleted));END//DELIMITER;-- 验证事件创建并查看状态SELECTEVENT_NAME,STATUS,EXECUTE_AT,INTERVAL_VALUE,INTERVAL_FIELDFROMinformation_schema.EVENTSWHEREEVENT_SCHEMA='test_db'ANDEVENT_NAME='ev_cleanup_old_logs';-- 启用事件(默认创建后即启用)ALTEREVENT ev_cleanup_old_logsENABLE;# 1. 检查从节点事件定义是否同步kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p -e" SELECT EVENT_NAME, STATUS, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD FROM information_schema.EVENTS WHERE EVENT_SCHEMA = 'test_db' AND EVENT_NAME = 'ev_cleanup_old_logs'; "# 2. 验证从节点 event_scheduler 状态(应为 OFF)kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p -e" SELECT @@event_scheduler; "# 3. 查看从节点事件详情kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p -e" SHOW CREATE EVENT test_db.ev_cleanup_old_logs\G "# 4. 等待1分钟后检查主节点执行结果kubectlexec-it -n qfusion-admin<primary-pod>-c mysql -- mysql -u root -p test_db -e" SELECT * FROM t_audit_log WHERE table_name = 'event_scheduler' ORDER BY created_at DESC LIMIT 5; "# 5. 验证从节点数据已同步(但事件未在从节点执行)kubectlexec-it -n qfusion-admin<secondary-pod>-c mysql -- mysql -u root -p test_db -e" SELECT * FROM t_audit_log WHERE table_name = 'event_scheduler' ORDER BY created_at DESC LIMIT 5; "| 检查项 | 命令 | 预期结果 |
|---|---|---|
| 主节点调度器 | SELECT @@event_scheduler | ON |
| 从节点调度器 | SELECT @@event_scheduler | OFF(重要!) |
| 事件定义同步 | SHOW EVENTS | 能查到 ev_cleanup_old_logs |
| 事件状态 | SELECT * FROM information_schema.EVENTS | STATUS=ENABLED |
| 主节点执行 | 检查 t_audit_log | 有执行记录 |
| 从节点数据 | 检查 t_audit_log | 数据已同步,但非本地执行 |
-- 生产环境建���:每天凌晨2点执行DROPEVENTIFEXISTSev_cleanup_old_logs;DELIMITER//CREATEEVENT ev_cleanup_old_logsONSCHEDULE EVERY1DAYSTARTS CONCAT(CURDATE()+INTERVAL1DAY,' 02:00:00')ONCOMPLETION PRESERVEDOBEGINDELETEFROMt_audit_logWHEREcreated_at<DATE_SUB(NOW(),INTERVAL90DAY)LIMIT10000;END//DELIMITER;-- 查看所有事件状态SELECTEVENT_NAME,STATUS,LAST_EXECUTED,ON_COMPLETION,INTERVAL_VALUE,INTERVAL_FIELDFROMinformation_schema.EVENTSWHEREEVENT_SCHEMA='test_db';#!/bin/bash# 完整的对象同步验证脚本NAMESPACE="qfusion-admin"PRIMARY_POD="<primary-pod-name>"SECONDARY_POD="<secondary-pod-name>"DB_USER="root"DB_PASS="<password>"DB_NAME="test_db"echo"=== 1. 检查复制状态 ==="kubectlexec-it -n$NAMESPACE$SECONDARY_POD-c mysql -- mysql -u$DB_USER-p$DB_PASS-e" SHOW SLAVE STATUS\G "|grep-E"Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_Error"echo-e"\n=== 2. 验证存储过程同步 ==="kubectlexec-it -n$NAMESPACE$SECONDARY_POD-c mysql -- mysql -u$DB_USER-p$DB_PASS-e" SELECT ROUTINE_NAME, CREATED FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = '$DB_NAME'; "echo-e"\n=== 3. 验证触发器同步 ==="kubectlexec-it -n$NAMESPACE$SECONDARY_POD-c mysql -- mysql -u$DB_USER-p$DB_PASS-e" SELECT TRIGGER_NAME, EVENT_OBJECT_TABLE FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = '$DB_NAME'; "echo-e"\n=== 4. 验证定时器同步 ==="kubectlexec-it -n$NAMESPACE$SECONDARY_POD-c mysql -- mysql -u$DB_USER-p$DB_PASS-e" SELECT EVENT_NAME, STATUS, LAST_EXECUTED FROM information_schema.EVENTS WHERE EVENT_SCHEMA = '$DB_NAME'; "echo-e"\n=== 5. 验证 GTID 一致性 ==="echo"主节点 GTID:"kubectlexec-it -n$NAMESPACE$PRIMARY_POD-c mysql -- mysql -u$DB_USER-p$DB_PASS-e" SELECT @@GLOBAL.GTID_EXECUTED; "echo"从节点 GTID:"kubectlexec-it -n$NAMESPACE$SECONDARY_POD-c mysql -- mysql -u$DB_USER-p$DB_PASS-e" SELECT @@GLOBAL.GTID_EXECUTED; "echo-e"\n=== 6. 检查 event_scheduler 状态 ==="echo"主节点:"kubectlexec-it -n$NAMESPACE$PRIMARY_POD-c mysql -- mysql -u$DB_USER-p$DB_PASS-e" SELECT @@event_scheduler; "echo"从节点:"kubectlexec-it -n$NAMESPACE$SECONDARY_POD-c mysql -- mysql -u$DB_USER-p$DB_PASS-e" SELECT @@event_scheduler; "| 节点 | 角色 | super_read_only | read_only | 说明 |
|---|---|---|---|---|
| mysql-65cbddad00-0 | PRIMARY | 0 | 0 | 可读写 |
| mysql-65cbddad01-0 | SECONDARY | 1 | 1 | 只读 |
| mysql-65cbddad02-0 | SECONDARY | 1 | 1 | 只读 |
| 节点 | 角色 | super_read_only | read_only | 说明 |
|---|---|---|---|---|
| mysql-a486e45d00-0 | Master | 0 | 0 | 可读写 |
| mysql-a486e45d01-0 | Slave | 1 | 0 | 只读 |
注意:主备集群的 Slave 节点read_only=1由配置文件/etc/mysql/ext.semi.cnf设置。
SHOWVARIABLESLIKE'event_scheduler';-- 或SELECT@@event_scheduler;-- MGR 集群SELECTMEMBER_HOST,MEMBER_PORT,MEMBER_STATE,MEMBER_ROLEFROMperformance_schema.replication_group_members;-- 主备集群SHOWSLAVESTATUS\G-- MGR 集群SHOWVARIABLESLIKE'group_replication%';-- 主备集群SHOWSLAVESTATUS\GSHOWMASTERSTATUS;-- 检查 GTID 执行情况SHOWVARIABLESLIKE'gtid%';SELECT@@GLOBAL.GTID_EXECUTED;-- 检查 binlog 位置SHOWMASTERSTATUS;-- MGR 集群 - 在 PRIMARY 节点执行SETGLOBALevent_scheduler=ON;-- 主备集群 - 在 Master 节点执行SETGLOBALevent_scheduler=ON;# 编辑配置文件kubectlexec-it -n qfusion-admin<pod-name>-c mysql --vi/etc/mysql/my.cnf# 修改 event_scheduler=0 为 event_scheduler=1# 然后重启 Podkubectl delete pod -n qfusion-admin<pod-name>幂等性设计: 确保对象可以被重复创建而不报错
DROPPROCEDUREIFEXISTSproc_name;CREATEPROCEDUREproc_name()...声明确定性: 函数应声明 DETERMINISTIC 或 NO SQL
CREATEFUNCTIONfunc_name()RETURNSINTDETERMINISTICREADSSQLDATABEGIN...避免不确定性操作: 不使用 RAND(), UUID(), NOW() 等不确定函数
-- 监控 MGR 状态SELECT*FROMperformance_schema.replication_group_member_stats;-- 监控主备延迟SHOWSLAVESTATUS\G-- 关注: Seconds_Behind_Master-- 监控事件执行SELECT*FROMinformation_schema.EVENTS;| 文件 | MGR 集群 | 主备集群 |
|---|---|---|
| 主配置 | /etc/mysql/my.cnf | /etc/mysql/my.cnf |
| 只读配置 | /etc/mysql/my.ro.cnf | /etc/mysql/my.ro.cnf |
| MGR配置 | /etc/mysql.cnf.d/mgr_group.cnf | 无 |
| 半同步配置 | 无 | /etc/mysql/ext.semi.cnf |
| 动态配置 | /etc/mysql.cnf.d/config_option.cnf | 同左 |
| 扩展配置 | /etc/mysql.cnf.d/mysql-expand.conf | 同左 |