暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL一个字符集转换的骚操作,酿下性能的苦果

502

这是学习笔记的第 2275篇文章

  今天处理了一个RDS的问题,突然想起了好几年前处理的一个性能案例,看似不经意的细节竟然让我对整个问题的过程有了更清晰的认识。

  整个细节可以参见我写的这篇文章的处理过程:力荐:一条update语句引发的“血案”

   

   当时有一个地方没有想明白,那就是里面的字段APNS_PUSH_ID为什么字符集会是latin1,而表的字符集却妥妥的是UTF8,看起来是一个不大可能出现的场景。

  下午在协助处理一个问题的时候,才突然明白,我来复现下这个问题。

  创建一张表test_charset,设置字符集为latin1 

    mysql> create table test_charset(id int primary key,name varchar(30),memo varchar(30)) charset=latin1;
    Query OK, 0 rows affected (0.12 sec)

    查看表结构,可以清晰的看到,字段是共享了表的默认字符集,没有显式显示出来。

      mysql> show create table test_charset\G
      *************************** 1. row ***************************
      Table: test_charset
      Create Table: CREATE TABLE `test_charset` (
      `id` int(11) NOT NULL,
      `name` varchar(30) DEFAULT NULL,
      `memo` varchar(30) DEFAULT NULL,
      PRIMARY KEY (`id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1
      1 row in set (0.01 sec)

      我们使用如下的语句来变更下表的字符集。

        mysql> alter table test_charset charset=utf8;
        Query OK, 0 rows affected (0.05 sec)
        Records: 0 Duplicates: 0 Warnings: 0

        这个时候再次查看就会发现,原本“继承”的latin1字符集现在显式显示出来了,表的字符集是utf8,但是字符类型的字段字符集依然是latin1

          mysql> show create table test_charset\G
          *************************** 1. row ***************************
          Table: test_charset
          Create Table: CREATE TABLE `test_charset` (
          `id` int(11) NOT NULL,
          `name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
          `memo` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
          PRIMARY KEY (`id`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8
          1 row in set (0.00 sec)

          如果后续再添加字段,不显式指定字符集。

            mysql> alter table test_charset add memo2 varchar(30);
            Query OK, 0 rows affected (0.14 sec)
            Records: 0 Duplicates: 0 Warnings: 0

            查看表结构会发现,新字段memo2的字符集就会是utf8

              mysql> show create table test_charset\G
              *************************** 1. row ***************************
              Table: test_charset
              Create Table: CREATE TABLE `test_charset` (
              `id` int(11) NOT NULL,
              `name` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
              `memo` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
              `memo2` varchar(30) DEFAULT NULL,
              PRIMARY KEY (`id`)
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8
              1 row in set (0.00 sec)

              好了,问题到了这里就相对有了一个思路。 

              那么产生最开始让人疑惑的问题原因是什么呢?就是哪个骚操作:

                mysql> alter table test_charset charset=utf8;

                这是一个表级属性的变更,注意MySQL里面字段,表,数据库都可以存在差异化的字符集设置。虽然可以支持,但是显然这样做是不合理的。 

                而如果要让字段的变更同时生效,应该使用convert to 语句,我们为了突出变化,改为utf8mb4字符集。

                  mysql> alter table test_charset convert to charset utf8mb4;          
                  Query OK, 0 rows affected (0.13 sec)
                  Records: 0 Duplicates: 0 Warnings: 0


                  mysql> show create table test_charset\G
                  *************************** 1. row ***************************
                  Table: test_charset
                  Create Table: CREATE TABLE `test_charset` (
                  `id` int(11) NOT NULL,
                  `name` varchar(30) DEFAULT NULL,
                  `memo` varchar(30) DEFAULT NULL,
                  `memo2` varchar(30) DEFAULT NULL,
                  PRIMARY KEY (`id`)
                  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
                  1 row in set (0.00 sec)

                  QQ群号:763628645

                  QQ群二维码如下, 添加请注明:姓名+地区+职位,否则不予通过


                  在看,让更多人看到

                  文章转载自杨建荣的学习笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论