追踪 MySQL utf8 与 utf8mb4 的问题

Posted

技术标签:

【中文标题】追踪 MySQL utf8 与 utf8mb4 的问题【英文标题】:Tracking down MySQL utf8 vs. utf8mb4 Issues 【发布时间】:2021-10-29 09:29:15 【问题描述】:

我们有一个完整的 utf8mb4 和 utf8mb4_unicode_ci 数据库。我什至导出了整个“项目”的所有 SQL 代码(通过 dbForge),并且在整个项目中找不到对 UTF8 的单个引用。我已验证所有表都使用正确的字符集和排序规则。

问题是每次我对我们的沙箱执行重置(它会重建数据库中的数据以进行测试)时,我在多个存储过程中都会收到以下错误:

SQLEXCEPTION:CORE_create_root_data:(HY000:3719) 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.

我不明白为什么会发生这种情况;在存储过程或它调用的存储过程或任何表的任何列中没有 UTF8 定义。我什至在调试模式下浏览了代码并追踪了触发这些警告的位置。这是一个简单地将根数据插入数据库的存储过程;并在调用返回时触发警告。这完全没有意义。例如:

下面是触发的处理程序:

    DECLARE CONTINUE HANDLER FOR SQLWARNING
BEGIN
    GET DIAGNOSTICS CONDITION 1 @p1 = RETURNED_SQLSTATE, @p2 = mysql_ERRNO, @p3 = MESSAGE_TEXT;
    IF @p1 REGEXP '^01' = 1 THEN
        SET @errortype = 'SQL WARNING';
    ELSEIF @p1 REGEXP '^02' = 1 THEN
        SET @errortype = 'NOT FOUND';
    ELSEIF @p1 REGEXP '^0[0-2]' = 0 THEN
        SET @errortype = 'SQLEXCEPTION';
    END IF;

    SET @full_error = CONCAT(@errortype, ':CORE_create_root_data:(', @p1, ':', @p2, ') ', @p3);
    SELECT
        @full_error;
END;

调用下面的存储过程(var_result 只是一个 BOOL 结果)。

CALL CORE_create_global_static_settings(in_password, var_result);

上面的代码是这样做的:

INSERT INTO global_static_setting (setting_category, setting_name, setting_value)
VALUES ('GLOBAL_VALUE', 'LIMIT_DEFAULT', 200);

从执行简单插入的 SP 返回时...触发 utf8 错误/警告。

知道这里发生了什么吗?

【问题讨论】:

【参考方案1】:

假设您的数据库名为testdb:以下查询为您提供了表的所有字符集:

SELECT c.character_set_name, t.table_name
  FROM information_schema.tables AS t
 INNER JOIN information_schema.collation_character_set_applicability AS c 
    ON c.collation_name = t.table_collation
 WHERE t.table_schema = "testdb";

以下显示了所有列的字符集,但只有当它们是文本数据类型时,您才会看到一个。如果结果太多,可以在WHERE 子句中过滤表名和列名,但即使在大数据库中utf8utf8mb4 也很容易发现:

SELECT character_set_name, column_name, table_name 
  FROM information_schema.COLUMNS
 WHERE table_schema = "testdb";

此外:存储过程和函数也有字符集。所以你必须:

    备份所有程序和功能, 删除过程和函数, 执行SET NAMES utf8mb4;,最后 重新创建过程和函数。

他们现在将拥有所有字符集utf8mb4

【讨论】:

非常感谢;在发布之前,我运行了类似的东西。一切都是utf8mb4。所有表格和列。还有其他可能有助于追踪它的想法吗? 存储过程也有字符集***.com/questions/11920153/…我希望它们不是那么多,因为你需要删除每一个utf8 做到了。我不得不删除并重新创建所有存储过程和函数(大约 100,000 行代码 LOL)。万分感谢!如果您更新答案以包含上述内容,我会将其标记为正确。再次感谢!【参考方案2】:

SQLEXCEPTION:CORE_create_root_data:(HY000:3719) 'utf8' 当前是字符集 UTF8MB3 的别名,但在未来版本中将是 UTF8MB4 的别名。请考虑使用 UTF8MB4 以便明确。

是一个警告。

多年前,MySQL 实现了一个不完整的 utf8 实现,但将其称为 utf8。现在它有一个完整的实现并称之为utf8mb4。旧的 utf8 现在有一个别名“utf8mb3”。 MySQL 想更改名称,但需要我们的帮助。

除非您明确需要“utf8mb3”,否则只要实际将“utf8”的任何用法更改为“utf8mb4”。更改中可能会有一些小问题,特别是如果您仍在运行版本 5.x。一旦你完全迁移到 8.0,航行应该会再次平静。

创建存储例程时,已建立的字符集和排序规则将存储为例程的属性。可能存储为“utf8”。

解决方法是确定您使用的是哪个字符集(utf8mb4 或 utf8mb3)并重新创建存储例程,

存在于 utf8mb3(旧的“utf8”)中的任何有效字符都可以在 utf8mb4(未来“utf8”)中使用。 (反之亦然,例如许多表情符号。)

【讨论】:

以上是关于追踪 MySQL utf8 与 utf8mb4 的问题的主要内容,如果未能解决你的问题,请参考以下文章

MySQL中utf8 && utf8mb4

浅谈MySQL中utf8和utf8mb4的区别

utf8与utf8mb4的区别

Mysql utf8mb3 utf8mb4 与UTF8 字符集参数(character_set_system)的说明

MySQL:Unknown character set:utf8mb4怎么解决?

MySQL之字符集