将MySQL UTF8迁移到UTF8MB4的问题和疑问

Ban*_*hee 7 mysql migrate utf-8 utf8mb4

我试图将我的UTF8 MySQL 5.5.30数据库转换为UTF8MB4.我看过这篇文章https://mathiasbynens.be/notes/mysql-utf8mb4但有一些问题.

我做过这些

ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Run Code Online (Sandbox Code Playgroud)

最后一个用62个表手动完成,其中一个给了我这个警告

13:08:30 ALTER TABLE bradspelold.games CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 101289 row(s)受影响,2警告:1071指定密钥太长; 最大密钥长度为767字节1071指定密钥太长; 最大密钥长度为767字节记录:101289重复:0警告:2 3.016秒

  1. 这是一个问题吗?我该怎么办才能修好它?

下一步是

ALTER TABLE table_name CHANGE column_name column_name
         VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Run Code Online (Sandbox Code Playgroud)
  1. 我不确定命令,为什么有2列名?
  2. 我应该只在VARCHAR(191)列上执行此操作吗?我不认为我有他们中的任何一个?
  3. 你知道更多这样的artickels解释了更多id详细的原因和方法吗?

编辑:

桌上游戏

CREATE  TABLE `games` (
        `id` int(10) unsigned NOT NULL DEFAULT \'0\',
        `name` varchar(255) NOT NULL,
        `description` mediumtext,
        `yearPublished` datetime NOT NULL,
        `minPlayers` int(10) unsigned NOT NULL,
        `maxPlayers` int(10) unsigned NOT NULL,
        `playingTime` varchar(127) NOT NULL,
        `grade` double NOT NULL DEFAULT \'0\',
        `updated` datetime NOT NULL,
        `forumParentId` int(10) unsigned DEFAULT \'0\',
        `lastVisited` datetime DEFAULT NULL,
        `inactivatedDate` datetime DEFAULT NULL,
        `bggGrade` double DEFAULT NULL,
        PRIMARY KEY (`id`),
        KEY `inactivatedDate` (`inactivatedDate`),
        KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
Run Code Online (Sandbox Code Playgroud)

编辑2:

    'CREATE TABLE `forum_threads` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `title` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
      `description` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
      `createdDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
      `createrId` int(10) unsigned DEFAULT NULL,
      `replys` int(10) unsigned NOT NULL DEFAULT ''0'',
      `lastPostUserId` int(10) unsigned DEFAULT NULL,
      `lastPostId` int(10) unsigned DEFAULT NULL,
      `forumId` int(10) unsigned DEFAULT NULL,
      `visits` int(10) unsigned NOT NULL DEFAULT ''0'',
      `lastPostCreated` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
      `lastPostNickName` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
      `createrNickName` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
      `solved` tinyint(1) NOT NULL DEFAULT ''0'',
      `locked` tinyint(1) NOT NULL DEFAULT ''0'',
      `lockedByUserId` int(10) unsigned NOT NULL DEFAULT ''0'',
      `lockedDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
      `alteredDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
      `alteredUserId` int(10) unsigned DEFAULT NULL,
      `glued` tinyint(1) NOT NULL DEFAULT ''0'',
      `pollId` int(10) unsigned DEFAULT NULL,
      `facebookPostId` bigint(20) DEFAULT NULL,
      `facebookImportedDate` datetime DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `FK_forum_threads_1` (`forumId`),
      KEY `FK_forum_threads_2` (`pollId`),
      KEY `createdDate` (`createdDate`),
      KEY `createrId` (`createrId`),
      KEY `lastPostCreated` (`lastPostCreated`),
      CONSTRAINT `FK_forum_threads_1` FOREIGN KEY (`forumId`) REFERENCES `forum` (`id`) ON DELETE CASCADE
    ) ENGINE=InnoDB AUTO_INCREMENT=4306 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci'

'CREATE TABLE `forum` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(80) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
  `description` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
  `createdDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
  `threads` int(10) unsigned NOT NULL DEFAULT ''0'',
  `createrId` int(10) unsigned DEFAULT NULL,
  `lastPostUserId` int(10) unsigned DEFAULT NULL,
  `lastThreadId` int(10) unsigned DEFAULT NULL,
  `parentForumId` int(10) unsigned DEFAULT NULL,
  `lastPostNickName` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
  `lastPostCreated` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
  `lastThreadTitle` varchar(80) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '''',
  `alteredDate` datetime NOT NULL DEFAULT ''0000-00-00 00:00:00'',
  `alteredUserId` int(10) unsigned DEFAULT NULL,
  `placeOrder` int(10) unsigned NOT NULL DEFAULT ''0'',
  `separator` tinyint(1) NOT NULL DEFAULT ''0'',
  `rightLevel` int(10) unsigned NOT NULL DEFAULT ''1'',
  `createChildForum` tinyint(3) unsigned NOT NULL DEFAULT ''1'',
  `createThreads` tinyint(3) unsigned NOT NULL DEFAULT ''1'',
  PRIMARY KEY (`id`),
  KEY `Index_1` (`id`,`parentForumId`)
) ENGINE=InnoDB AUTO_INCREMENT=375 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci'
Run Code Online (Sandbox Code Playgroud)

Ric*_*mes 5

  1. INDEX的大小有限制。您遇到了限制,因为utf8mb4 每个字符最多需要4 个字节,而utf8仅需要3 个字节。同时INDEX大小限制以字节单位

“解决方案”是决定如何处理超大索引。(下面有更多内容)

2。

ALTER TABLE t CHANGE col col ...
Run Code Online (Sandbox Code Playgroud)

与更逻辑的相同

ALTER TABLE t MODIFY col ...
Run Code Online (Sandbox Code Playgroud)

前者允许您更改列的名称,因此在不需要更改名称时可以复制列名称的两个副本。

  1. 您很可能VARCHAR(255)在utf8中占用了767个字节(3 * 255 + 2;“ 2”是长度字段的大小)。4字节utf8mb4中的等效项为(191)(4 * 191 + 2 = 766;不能容纳191以上)。

  2. 我还没有看过有关它的文章。我怀疑我刚才说的是大部分需要说的话。

所以...

计划A:您是否拥有foo VARCHAR(255)utf8?(现在和将来)其中的数据是否总是少于191个字符?如果是这样,则只需执行ALTER。

方案B:如果需要的数量超过191,是否真的需要INDEX?DROP INDEX可能是替代方法。

方案C:或者,您可以使用“前缀”索引: INDEX(foo(191)),同时保留它VARCHAR(255)。通常,“前缀”索引是无用的,但是您可能有一个适用的用例。

要对此进行进一步讨论,请提供SHOW CREATE TABLE相关表格,并讨论该特定字段及其索引的含义。


Mah*_*ito 5

DB="database_name"
USER="mysql_user"
PASS="mysql_password"
(
    echo 'ALTER DATABASE `'"$DB"'` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'
    mysql -p$PASS -u $USER "$DB" -e "SHOW TABLES" --batch --skip-column-names \
    | xargs -I{} echo 'ALTER TABLE `'{}'` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'
) \
| mysql -p$PASS -u $USER "$DB"
Run Code Online (Sandbox Code Playgroud)
  • 要获取您工作的脚本,请打开命令行并使用以下步骤:

    1. 纳米convert_to_utf8mb4.sh
    2. 粘贴脚本并保存
    3. sudo chmod 755 Convert_to_utf8mb4.sh (在终端中)
    4. 输入 ./convert_to_utf8mb4.sh 运行脚本

    是的,排序规则已更改!