GreatSQL社区

搜索

GreatSQL社区

GreatSQL 8.0回流MySQL 5.7--存储过程导致复制中断

GreatSQL社区 已有 6 次阅读2026-10-28 14:08 |系统分类:运维实战

  • 1. 问题描述
  • 2. 问题分析
  • 3. 总结

1. 问题描述

某银行客户从 MySQL 5.7 迁移到 GreatSQL 8.0,要求迁移完成后生产数据回流到 MySQL 5.7 一段时间,以备紧急回切和数据对比。在进行回流测试时,在 GreatSQL 8.0 侧执行的存储过程,其 binlog 中记录了 SET @@session.character_set_client=255,255 对应的排序规则 utf8mb4_0900_ai_ci ,是 MySQL/GreatSQL 8.0 新引入的排序规则,MySQL 5.7 不能识别,导致 slave 端 MySQL 5.7 的 SQL 线程中断。

报错信息如下:

mysql > select * from performance_schema.replication_applier_status_by_worker limit 1\G
*************************** 1. row ***************************
         CHANNEL_NAME: 
            WORKER_ID: 1
            THREAD_ID: NULL
        SERVICE_STATE: OFF
LAST_SEEN_TRANSACTION: 195bbb58-b72a-11f1-9e63-fa163e5eebc2:6
    LAST_ERROR_NUMBER: 22
   LAST_ERROR_MESSAGE: Worker 1 failed executing transaction '195bbb58-b72a-11f1-9e63-fa163e5eebc2:6' at master log binlog.000928, end_log_pos 119877602; Error 'Character set '#255' is not a compiled character set and is not specified in the '/data/actiondb/base/5.7.44/share/charsets/Index.xml' file' on query. Default database: 'xxx_yyy_batch'. Query: 'TRUNCATE TABLE OOOOO_ORDER'
 LAST_ERROR_TIMESTAMP: 2026-10-15 04:29:20
1 row in set (0.00 sec)

解析该事务对应的 binlog,信息如下:

SET @@SESSION.GTID_NEXT= '195bbb58-b72a-11f1-9e63-fa163e5eebc2:6'/*!*/;
# at 119877488
#261015  4:29:20 server id 1034607900  end_log_pos 119877602 CRC32 0x774776ac   Query   thread_id=3623014       exec_time=0     error_code=0    Xid = 13469999
use `xxx_yyy_batch`/*!*/;
SET TIMESTAMP=1792009760/*!*/;
SET @@session.pseudo_thread_id=3623014/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113664/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=255,@@session.collation_connection=45,@@session.collation_server=46/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=45*//*!*/;
TRUNCATE TABLE OOOOO_ORDER
/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

存储过程 proc_rept_ooooo_order 的创建信息如下:

GreatSQL > show create procedure proc_rept_ooooo_order\G 
*************************** 1. row ***************************
           Procedure: PROC_REPT_OOOOO_ORDER
            sql_mode: STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
    Create Procedure: CREATE DEFINER=`run_batch`@`%` PROCEDURE `PROC_REPT_OOOOO_ORDER`( IN PETLDATE CHAR(8),OUT PCODE INT,OUT PMSG VARCHAR (80))
BEGIN
......
CALL PPPP_SSS_RUN_BATCH_LOG ( PETLDATE, PRC_NAME, PRC_STEP, PRC_DESC );
TRUNCATE TABLE OOOOO_ORDER;
......
END
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
  Database Collation: utf8mb4_general_ci
1 row in set (0.00 sec)

2. 问题分析

2.1 实验验证:探究 binlog 中字符集信息的来源

  1. 在 GreatSQL 中,直接设置 character_set_client、collation_connection、collation_server 为特定的值(224,225,226),检查存储过程执行后的 binlog 信息。
GreatSQL > select * from information_schema.collations where CHARACTER_SET_NAME='utf8mb4';
+----------------------------+--------------------+-----+------------+-------------+---------+---------------+
| COLLATION_NAME             | CHARACTER_SET_NAME | ID  | IS_DEFAULT | IS_COMPILED | SORTLEN | PAD_ATTRIBUTE |
+----------------------------+--------------------+-----+------------+-------------+---------+---------------+
| utf8mb4_general_ci         | utf8mb4            |  45 |            | Yes         |       1 | PAD SPACE     |
| utf8mb4_bin                | utf8mb4            |  46 |            | Yes         |       1 | PAD SPACE     |
| utf8mb4_unicode_ci         | utf8mb4            | 224 |            | Yes         |       8 | PAD SPACE     |
| utf8mb4_icelandic_ci       | utf8mb4            | 225 |            | Yes         |       8 | PAD SPACE     |
| utf8mb4_latvian_ci         | utf8mb4            | 226 |            | Yes         |       8 | PAD SPACE     |
| utf8mb4_romanian_ci        | utf8mb4            | 227 |            | Yes         |       8 | PAD SPACE     |
| utf8mb4_slovenian_ci       | utf8mb4            | 228 |            | Yes         |       8 | PAD SPACE     |
......

GreatSQL > SET @@session.character_set_client=224,@@session.collation_connection=225,@@session.collation_server=226;
Query OK, 0 rows affected (0.02 sec)

GreatSQL > show variables like '%colla%';
+-------------------------------+----------------------+
| Variable_name                 | Value                |
+-------------------------------+----------------------+
| collation_connection          | utf8mb4_icelandic_ci |
| collation_database            | utf8mb4_bin          |
| collation_server              | utf8mb4_latvian_ci   |
| default_collation_for_utf8mb4 | utf8mb4_general_ci   |
+-------------------------------+----------------------+
4 rows in set (0.06 sec)

GreatSQL > drop PROCEDURE testchar3;
Query OK, 0 rows affected (0.16 sec)

GreatSQL > CREATE PROCEDURE testchar3() truncate table test2 ;
Query OK, 0 rows affected (0.01 sec)

GreatSQL > show procedure status like 'testchar3';
+------+-----------+-----------+-----------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| Db   | Name      | Type      | Definer   | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |
+------+-----------+-----------+-----------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| test | testchar3 | PROCEDURE | greatdb@% | 2026-10-19 16:25:43 | 2026-10-19 16:25:43 | DEFINER       |         | utf8mb4              | utf8mb4_icelandic_ci | utf8mb4_bin        |
+------+-----------+-----------+-----------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
1 row in set (0.03 sec)

执行 testchar3 后的 binlog 信息:

SET @@SESSION.GTID_NEXT= '684af664-79a4-11f1-9869-00163e883d79:68'/*!*/;
# at 5739
#261019 16:26:54 server id 1004003306  end_log_pos 5838 CRC32 0x3be26de4        Query   thread_id=93    exec_time=0     error_code=0    Xid = 484
use `test`/*!*/;
SET TIMESTAMP=1792398414/*!*/;
SET @@session.pseudo_thread_id=93/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=224,@@session.collation_connection=225,@@session.collation_server=226/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=45*//*!*/;
truncate table test2
/*!*/;

可看出:binlog 中 character_set_client 来自存储过程创建时,指定的系统变量 character_set_client 的数字值(排序规则 224)。

  1. 重新登录数据库,在 collation_server=utf8mb4_bin(46)下运行存储过程 testchar3,解析后 binlog 信息,binlog 中其他信息未改变,只改变了 @@session.collation_server=46 。
SET @@session.character_set_client=224,@@session.collation_connection=225,@@session.collation_server=46/*!*/;

可以得出:

binlog 中记录的字符集排序规则信息来源:

  • character_set_client-- 存储过程定义时的客户端排序规则(client_collation_id)。
  • collation_connection -- 存储过程定义时的连接排序规则(connection_collation_id)。
  • collation_server-- 存储过程运行时的服务器排序规则(collation_server)。

2.2 检查表 routines 的数据来源

那 information_schema.routines 里为什么只看到 character_set_client: utf8mb4(字符集名称),却看不到 224 这个数字?

检查 information_schema.routines 的创建信息:

GreatSQL > show create table information_schema.routines\G
*************************** 1. row ***************************
                View: ROUTINES
         Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `ROUTINES` AS select `rtn`.`name` AS `SPECIFIC_NAME`,(`cat`.`name` collate utf8mb3_tolower_ci) AS `ROUTINE_CATALOG`,(`sch`.`name` collate utf8mb3_tolower_ci) AS `ROUTINE_SCHEMA`,`rtn`.`name` AS `ROUTINE_NAME`,`rtn`.`type` AS `ROUTINE_TYPE`,if((`rtn`.`type` <> 'FUNCTION'),'',substring_index(substring_index(`rtn`.`result_data_type_utf8`,'(',1),' ',1)) AS `DATA_TYPE`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,`rtn`.`result_numeric_precision` AS `NUMERIC_PRECISION`,`rtn`.`result_numeric_scale` AS `NUMERIC_SCALE`,`rtn`.`result_datetime_precision` AS `DATETIME_PRECISION`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) else NULL end) AS `COLLATION_NAME`,if((`rtn`.`type` <> 'FUNCTION'),NULL,`rtn`.`result_data_type_utf8`) AS `DTD_IDENTIFIER`,'SQL' AS `ROUTINE_BODY`,if(can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,true),`rtn`.`definition_utf8`,NULL) AS `ROUTINE_DEFINITION`,NULL AS `EXTERNAL_NAME`,`rtn`.`external_language` AS `EXTERNAL_LANGUAGE`,'SQL' AS `PARAMETER_STYLE`,if((`rtn`.`is_deterministic` = 0),'NO','YES') AS `IS_DETERMINISTIC`,`rtn`.`sql_data_access` AS `SQL_DATA_ACCESS`,NULL AS `SQL_PATH`,`rtn`.`security_type` AS `SECURITY_TYPE`,`rtn`.`created` AS `CREATED`,`rtn`.`last_altered` AS `LAST_ALTERED`,`rtn`.`sql_mode` AS `SQL_MODE`,`rtn`.`comment` AS `ROUTINE_COMMENT`,`rtn`.`definer` AS `DEFINER`,`cs_client`.`name` AS `CHARACTER_SET_CLIENT`,`coll_conn`.`name` AS `COLLATION_CONNECTION`,`coll_db`.`name` AS `DATABASE_COLLATION` from ((((((((`mysql`.`routines` `rtn` join `mysql`.`schemata` `sch` on((`rtn`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll_client` on((`coll_client`.`id` = `rtn`.`client_collation_id`))) join `mysql`.`character_sets` `cs_client` on((`cs_client`.`id` = `coll_client`.`character_set_id`))) join `mysql`.`collations` `coll_conn` on((`coll_conn`.`id` = `rtn`.`connection_collation_id`))) join `mysql`.`collations` `coll_db` on((`coll_db`.`id` = `rtn`.`schema_collation_id`))) left join `mysql`.`collations` `coll_result` on((`coll_result`.`id` = `rtn`.`result_collation_id`))) left join `mysql`.`character_sets` `cs_result` on((`cs_result`.`id` = `coll_result`.`character_set_id`))) where (0 <> can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,false))
character_set_client: utf8mb3
collation_connection: utf8mb3_general_ci
1 row in set (0.00 sec)

由视图的构建可知:

information_schema.routines 是源于 mysql.routines,在 mysql.routines 中存储的是 client_collation_id(客户端排序规则),但在 information_schema.routines 中 CHARACTER_SET_NAME 显示的不是 client_collation_id(排序规则),而是其对应的字符集名称。

information_schema.routines(CHARACTER_SET_CLIENT)
                                       ▲
                                       │  select  cs_client.name  AS CHARACTER_SET_CLIENT
mysql.character_sets(character_set_id,name)  cs_client
                      ▲  on  cs_client.id = coll_client.character_set_id
                      │
    mysql.collations(id)  coll_client
                      ▲  on  coll_client.id = rtn.client_collation_id
                      │
mysql.routines(client_collation_id)  rtn

2.3 处理方法

解决存储过程使用 utf8mb4_0900_ai_ci(255)导致无法回流到 MySQL 5.7 的问题,可以在 GreatDB 中,在 MySQL 5.7 识别的 character_set_client 下,重新创建存储过程。

如:在 utf8mb4_bin 下重新创建存储过程:

-- 1、设置会话的character_set_client
set names utf8mb4 collate utf8mb4_bin; 
-- 或者直接设置character_set_client
SET @@session.character_set_client=46; -- 排序规则utf8mb4_bin


-- 2、重新编译存储过程和函数
drop procedure xxxx ;
create procedure xxxx ....

3. 总结

由于 GreatSQL 与 MySQL 高度兼容,MySQL 5.7 迁移到 GreatSQL 8.0 的步骤比较简单,可以使用 GreatSQL 8.0 软件可以直接打开 MySQL 5.7 的数据库文件,GreatSQL 8.0 实例启动时会自动完成数据库字典的升级。

升级后,如果需要异步复制方式从 GreatSQL 8.0 回流到 MySQL 5.7,请注意不能在 GreatSQL 8.0 执行 MySQL5.7 不识别的命令、不能使用 MySQL 5.7 不识别的字符集和排序规则。由于升级后的存储程序(包括:存储过程 procedure、函数 function、自动调度事件 event)中记录的排序规则是 utf8mb4 的默认排序规则 utf8mb4_0900_ai_ci(编号 255),属于 MySQL 5.7 不识别的排序规则,这些存储程序需要在 MySQL 5.7 识别的排序规则下重新创建。




评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

合作电话:010-64087828

社区邮箱:greatsql@greatdb.com

社区公众号
社区小助手
QQ群
GMT+8, 2026-11-3 10:50 , Processed in 0.041279 second(s), 9 queries , Redis On.
返回顶部