【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
相关推荐
济6177 小时前
ARM Linux 驱动开发篇----字符设备驱动开发(2)--字符设备驱动开发步骤---- Ubuntu20.04
linux·运维·服务器
无名-CODING7 小时前
SpringMVC处理流程完全指南:从请求到响应的完整旅程
java·后端·spring
瑶山7 小时前
Spring Cloud微服务搭建三、分布式任务调度XXL-JOB
java·spring cloud·微服务·xxljob
仗剑天涯 回首枉然7 小时前
Linux 和 windows 共享文件
linux·运维·windows
Re.不晚7 小时前
深入底层理解HashMap——妙哉妙哉的结构!!
java·哈希算法
zzzsde7 小时前
【Linux】进程(3):进程状态
linux·运维·服务器
Mr_liu_6667 小时前
ubuntu:beyond compare 4 This license key has been revoked——————转载拼接
linux·运维·ubuntu
无聊的小坏坏7 小时前
补充:使用 /etc/cron.d 管理定时任务
linux·定时任务
Serene_Dream7 小时前
Java 内存区域
java·jvm
热爱生活的五柒7 小时前
linux/mac/wsl如何使用claude code,并配置免费的硅基流动API?(官方的需要付费订阅)
linux·运维·macos