【问题标题】:MariaDB will not change the collation for a databaseMariaDB 不会更改数据库的排序规则
【发布时间】:2016-10-15 21:28:09
【问题描述】:

我已经在 StackOverflow 上研究这个问题超过 24 小时,并决定尽管有很多关于同一主题的问答,但其他地方还没有涉及到这个问题。

我在 MariaDB 10.1 上使用 HeidiSQL 9.3,但有一个奇怪的问题如下:我最初在创建数据库时接受了默认排序规则,然后意识到这不是我想要的并尝试更改它

ALTER DATABASE InternalFulfillment CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

这不起作用,数据库仍然报告为ucs2_bin,所有过程和函数也是ucs2_bin。我尝试了所有可以在 StackOverflow 上找到的问答中的所有建议,包括以下陈述:

SET collation_connection = 'utf8mb4_unicode_ci';
SET NAMES 'utf8mb4';
SET CHARACTER SET 'utf8mb4';

当我删除并重新创建程序时,它们仍然以ucs2_bin 的形式返回。

最奇怪的是,如果我删除并重新创建名为“InternalFulfilment”的数据库,排序规则是错误的,但如果我创建一个不同名称的数据库,那么我会得到我想要的排序规则,并运行脚本创建存储过程的创建过程使用utf8mb4_unicode_ci 排序规则。

似乎 MariaDB 和/或 HeidiSQL 正在记住我第一次创建“InternalFulfillment”数据库时使用的原始排序规则,并且每当我创建具有此名称的数据库时始终使用 ucs2_bin 排序规则。

有谁知道这可能存储在哪里,以便我清除它。谢谢。

阅读以下答案后的其他 cmets

隔夜离开后,第二天早上我能够删除并使用不同的排序规则重新创建数据库,但现在它卡在新的排序规则上。

接着@Anse 的回答:

DROP DATABASE IF EXISTS `InternalFulfillment`;

CREATE DATABASE `InternalFulfillment` /*!40100 COLLATE 'ucs2_bin' */;

USE `InternalFulfillment`;

CREATE TABLE `table1` (
    `column1` VARCHAR(50) NULL
)
COLLATE='ucs2_bin'
ENGINE=InnoDB;

DELIMITER //
CREATE DEFINER=`root`@`%` PROCEDURE `proc1`(IN `param1` VARCHAR(50))
    DETERMINISTIC
BEGIN
    SELECT
        column1
    FROM
        table1 t
    WHERE
        t.column1 = param1;
END//
DELIMITER ;

CALL proc1('test');

产生:/* SQL Error (1267): Illegal mix of collations (ucs2_bin,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operation '=' */。如果我用utf8mb4_general_ci 重新运行这个脚本,那么它会正确完成。

昨天我的数据库卡在ucs2_bin,今天它卡在utf8mb4_general_ci,所以有些东西被缓存了相当长的过期时间。

【问题讨论】:

  • 有趣的琐事问题。请注意,有服务器全局级别和会话级别变量。另见dev.mysql.com/doc/refman/5.5/en/create-database.html
  • 我写了这个Here 用于将客户端和会话变量快照作为存根。还和 Rick 聊了聊Here ... 搞砸了一段时间,然后我自己更进一步。我会 ping Rick 看看。
  • 想知道您使用的是哪个 MariaDB 吗? select * from information_schema.schemata where schema='InternalFulfillment' 返回什么?您是否也尝试过使用命令行客户端?

标签: mysql database mariadb heidisql


【解决方案1】:

看起来 MariaDB 中有一些排序规则缓存。我是 HeidiSQL 的作者,我很确定 HeidiSQL 本身没有这样的排序规则缓存,所以它一定是 MySQL 和/或 MariaDB 的问题。

但是,我只是尝试在本地 Windows 上的 MySQL v5.7.9 服务器上重现该问题,但没有运气:

CREATE DATABASE `InternalFulfillment` /*!40100 COLLATE 'ucs2_bin' */;
CREATE TABLE `table1` (
    `Column 1` VARCHAR(50) NULL
)
COLLATE='ucs2_bin'
ENGINE=InnoDB;

数据库和 table1 都具有 ucs2_bin 排序规则,正如预期的那样。

ALTER DATABASE `internalfulfillment` COLLATE 'utf8mb4_general_ci';
CREATE TABLE `table2` (
    `Column 1` VARCHAR(50) NULL
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB;

现在,数据库和新创建的 table2 按预期报告更改的排序规则:

SELECT `DEFAULT_COLLATION_NAME` FROM `information_schema`.`SCHEMATA`
  WHERE `SCHEMA_NAME`='internalfulfillment';
>> utf8mb4_general_ci

SELECT TABLE_NAME, TABLE_COLLATION FROM `information_schema`.`TABLES`
  WHERE TABLE_SCHEMA='internalfulfillment';

TABLE_NAME | TABLE_COLLATION 
table1 | ucs2_bin 
table2 | utf8mb4_general_ci

所以,我猜你在 MariaDB 中遇到了一个错误。

【讨论】:

  • 感谢您对 HeidiSQL 的反馈。请参阅上述问题中的其他 cmets。我认为您是对的,这一定是 MariaDB 10.1 中的错误。我会把你的答案标记为正确的。
  • @bikeman868 这个错误已经提交了吗?它似乎仍然存在于 MariaDB 10.5.5 中。
  • 我让我的 MariaDB 实例恢复到一个状态,它现在将通过执行几个 FLUSH QUERY CACHE; FLUSH TABLES; USE SomeDatabase; 语句立即应用 alter database 语句(并更新其内部状态)。它没有深入挖掘它为什么起作用,但确实如此。之后,创建和更改数据库现在就可以正常工作了。
【解决方案2】:

检查这些:

SHOW VARIABLES LIKE 'char%'; -- If anything say 'ucs2...', you should change it
SHOW CREATE DATABASE ...; -- The /*!40100 */ 'comment' is for hiding the clause for old versions.
SHOW CREATE PROCEDURE ...\G

一些基础知识(您似乎已经了解):

数据库中的CHARACTER SET 和COLLATION 只是默认值,当您在不指定CREATE TABLE 时使用它们。

同样,为表指定的CHARACTER SET 和COLLATION 只是列的默认值。

要更改给定列的COLLATION,您需要使用ALTER TABLE ... MODIFY COLUMN ...。

要更改默认值,可以在数据库或表上使用ALTER;但这只会影响未来表或列。

另一个问题... 任何存储例程的CHARACTER SET 和COLLATION 在声明例程时定义。要更改其中一个或两个,您必须 DROP 和 reCREATE 例程。

今后,utf8mb4 是主要使用的CHARACTER SET。 ucs2(和大多数其他字符集)几乎不应该被使用。如果您能发现“ucs2”的起源,请将其根除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 2013-08-05
    • 1970-01-01
    • 2014-11-25
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多