追踪 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 名称和列名中过滤,但即使在大数据库 utf8
中 utf8mb4
也很容易发现:
SELECT character_set_name, column_name, table_name
FROM information_schema.COLUMNS
WHERE table_schema = "testdb";
此外:存储过程和函数也有字符集。所以你必须:
- 备份所有程序和函数,
- 删除过程和函数,
- 执行
SET NAMES utf8mb4;
,最后
- 重新创建过程和函数。
他们现在将拥有所有字符集 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”)中工作。 (反之亦然,例如许多表情符号。)
我们有一个完全是 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 名称和列名中过滤,但即使在大数据库 utf8
中 utf8mb4
也很容易发现:
SELECT character_set_name, column_name, table_name
FROM information_schema.COLUMNS
WHERE table_schema = "testdb";
此外:存储过程和函数也有字符集。所以你必须:
- 备份所有程序和函数,
- 删除过程和函数,
- 执行
SET NAMES utf8mb4;
,最后 - 重新创建过程和函数。
他们现在将拥有所有字符集 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”)中工作。 (反之亦然,例如许多表情符号。)