【1267 - Illegal mix of collations 】mysql报错解决记录

这是我的表:

sql 复制代码
CREATE TABLE `collect_data_node` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `node_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '节点ip',
  `measure_frequency` double DEFAULT NULL COMMENT '测量频率',
  `measure_bandwidth` bigint(20) DEFAULT NULL COMMENT '测量带宽',
  `measure_power` float DEFAULT NULL COMMENT '测量功率',
  `monitor_model` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '监测模式',
  `collect_time` datetime DEFAULT NULL COMMENT '采集时间',
  `channel_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4296575 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='信号检测节点采集数据表';
sql 复制代码
CREATE DEFINER=`root`@`%` PROCEDURE `clean_up_old_data`(IN nodeIps TEXT, IN amount INT)
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE cur_nodeIp VARCHAR(255);
    DECLARE cur_count INT;
    DECLARE cur CURSOR FOR
        SELECT DISTINCT node_ip
        FROM collect_data_node
        WHERE FIND_IN_SET(node_ip, nodeIps);
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    OPEN cur;
    read_loop: LOOP
        FETCH cur INTO cur_nodeIp;
        IF done THEN
            LEAVE read_loop;
        END IF;

        -- 计算当前 nodeIp 的记录数
        SELECT COUNT(*)
        INTO cur_count
        FROM collect_data_node
        WHERE node_ip = cur_nodeIp;

        -- 如果当前 nodeIp 的记录数超过指定数量,则删除多余记录
        IF cur_count > amount THEN
            DELETE FROM collect_data_node
            WHERE node_ip = cur_nodeIp 
            and id NOT IN (
                SELECT id FROM (
                    SELECT id
                    FROM collect_data_node
                    WHERE node_ip = cur_nodeIp
                    ORDER BY collect_time DESC
                    LIMIT amount
                ) AS temp
            );
        END IF;
    END LOOP;
    CLOSE cur;
END
sql 复制代码
CALL clean_up_old_data2 (
	'97bfc421-94ef-4a58-8be2-7234baf3954d',
1000 
)

当我调用这个存储过程会报错:

1267 - Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT) and (utf8mb4_unicode_ci,IMPLICIT) for operation 'find_in_set'

find_in_set中涉及了排序

node_ip排序规则是:utf8mb4_0900_ai_ci,而输入变量nodeIps用的是默认的排序规则utf8mb4_unicode_ci。两个排序规则不一样,就报这个错了。

查看数据默认使用的排序规则:

sql 复制代码
SHOW VARIABLES LIKE 'collation_server';

发现是utf8mb4_unicode_ci

解决方案

创建表的时候排序规则指定成数据库默认的排序规则。

修改存储过程,有涉及到排序的手动指定排序规则,保持一致的排序规则。

sql 复制代码
CREATE DEFINER=`root`@`%` PROCEDURE `clean_up_old_data`(IN nodeIps TEXT, IN amount INT)
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE cur_nodeIp VARCHAR(255);
    DECLARE cur_count INT;
    DECLARE cur CURSOR FOR
        SELECT DISTINCT node_ip
        FROM collect_data_node
        WHERE FIND_IN_SET(
    node_ip COLLATE utf8mb4_unicode_ci,
    nodeIps COLLATE utf8mb4_unicode_ci
);
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    OPEN cur;
    read_loop: LOOP
        FETCH cur INTO cur_nodeIp;
        IF done THEN
            LEAVE read_loop;
        END IF;

        -- 计算当前 nodeIp 的记录数
        SELECT COUNT(*)
        INTO cur_count
        FROM collect_data_node
        WHERE node_ip COLLATE utf8mb4_0900_ai_ci = cur_nodeIp COLLATE utf8mb4_0900_ai_ci;

        -- 如果当前 nodeIp 的记录数超过指定数量,则删除多余记录
        IF cur_count > amount THEN
            DELETE FROM collect_data_node
            WHERE node_ip COLLATE utf8mb4_0900_ai_ci = cur_nodeIp COLLATE utf8mb4_0900_ai_ci

            and id NOT IN (
                SELECT id FROM (
                    SELECT id
                    FROM collect_data_node
										WHERE node_ip COLLATE utf8mb4_0900_ai_ci = cur_nodeIp COLLATE utf8mb4_0900_ai_ci
                    ORDER BY collect_time DESC
                    LIMIT amount
                ) AS temp
            );
        END IF;
    END LOOP;
    CLOSE cur;
END
相关推荐
折哥的程序人生 · 物流技术专研2 分钟前
《Java 100 天进阶之路》第50篇:阻塞队列与并发容器(2026版)
java·面试题·java进阶·blockingqueue·并发容器·集合源码·java100天进阶
ai_coder_ai20 分钟前
编写自动化脚本,在自己后端服务中使用Open Api进行设备相关操作
java·运维·自动化
大圣编程27 分钟前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang28 分钟前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
硕风和炜38 分钟前
【LeetCode: 2492. 两个城市间路径的最小分数 + DFS】
java·算法·leetcode·深度优先·dfs·bfs·并查集
格子软件1 小时前
2026年GEO贴牌代理:分布式多级分账状态机源码深度解构
java·vue.js·分布式·vue·geo
之歆1 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
会周易的程序员1 小时前
microLog 的本地日志读取接口 log_reader — 本地日志文件读取工具开发指南
linux·物联网·架构·嵌入式·日志·iot·aiot
我是一颗柠檬2 小时前
【Java项目技术亮点】加权轮询负载均衡算法
java·算法·负载均衡
灯厂码农2 小时前
C语言动态内存分配完全指南(malloc、calloc、realloc、free)
java·c语言·算法