追踪 MySQL utf8 与 utf8mb4 问题

Tracking down MySQL utf8 vs. utf8mb4 Issues

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

问题是每次我在我们的沙箱上执行重置(出于测试目的重建数据库中的数据)时,我在多个存储过程中遇到以下错误:

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.

我不明白为什么会这样;存储过程或它调用的存储过程或任何 table 的任何列中没有 UTF8 定义。我什至在调试模式下遍历代码并追踪这些警告被触发的位置。它是一个简单地将根数据插入数据库的存储过程;并且在调用的 return 处触发警告。这完全没有意义。例如:

下面是触发的处理程序:

    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);

在 return 从执行简单插入的 SP 中...它触发 utf8 error/warning。

知道这里发生了什么吗?

假设你的数据库名为testdb:下面的查询给你tables的所有字符集:

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 子句 table 名称和列名中过滤,但即使在大数据库 utf8utf8mb4 也很容易发现:

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

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

  1. 备份所有程序和函数,
  2. 删除过程和函数,
  3. 执行SET NAMES utf8mb4;,最后
  4. 重新创建过程和函数。

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

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.

是警告。

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

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

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

修复方法是确定您正在使用的字符集(utf8mb4 或 utf8mb3)并重新创建存储例程,

utf8mb3(旧的“utf8”)中存在的任何有效字符都将在 utf8mb4(future“utf8”)中工作。 (反之亦然,例如许多表情符号。)