MySQL修改数据类型的问题总结

开发的同事找我说有个紧急需求,负责这个业务的DBA同事回家了,想让我帮忙看看,运行个SQL语句,几秒钟就好。我一听,就本着人道主义的精神留下来处理,但是发现似乎留给我的是一个大坑。

了解了问题之后,让我有些后背发凉,这个表根据开发同事反馈有20亿的数据,这得多大的一个表啊,当前的问题是这个表里的主键id数据类型是int,因为数据类型的限制已经达到了最大值,现在插入不了数据了。希望我帮忙处理一下,把数据类型修改为bigint.

我们简单来了解一下MySQL的数据类型。

对于数据类型有下面的一些总结,更详细可以参见 

类型大小范围(有符号)范围(无符号)用途
TINYINT   1 字节   (-128,127)   (0,255)   小整数值  
SMALLINT   2 字节   (-32 768,32 767)   (0,65 535)   大整数值  
MEDIUMINT   3 字节   (-8 388 608,8 388 607)   (0,16 777 215)   大整数值  
INT或INTEGER   4 字节   (-2 147 483 648,2 147 483 647)   (0,4 294 967 295)   大整数值  
BIGINT   8 字节   (-9 233 372 036 854 775 808,9 223 372 036 854 775 807)   (0,18 446 744 073 709 551 615)   极大整数值  

所以现在的int数据类型已经达到了最大值2 147 483 647。

修改数据类型,扩展一般是可行的,但是这个环境MySQL版本还比较低,所以pt-osc的工具是别想了,而且20亿的数据就算处理也得耗上不少的时间。

简答了解了下问题,我一直纠结这个修改数据类型的操作影响时长。

20亿的数据做这样的操作,想必经历的人也不会太多,偏偏当了友情支持,我登录到指定的环境,仔细一看,这个表原来没有20亿的数据,只是id递增到了20亿的级别,表里有几百万的数据,对应的数据文件看有500M左右,所以这个问题让我悬着的心终于踏实了一些。

# ll -h activity_dj_actor_info_log*

-rw-rw---- 1 mysql mysql 8.7K Sep 29  2014 activity_dj_actor_info_log.frm

-rw-rw---- 1 mysql mysql 560M Nov  4 19:05 activity_dj_actor_info_log.ibd

这个修改数据类型的操作持续了大概1分多钟就结束了。

提供的语句如下:

> ALTER TABLE activity_dj_actor_info_log modify id  BIGINT;
 Query OK, 3144626 rows affected (1 min 22.64 sec)
 Records: 3144626  Duplicates: 0  Warnings: 0
查看线程的情况,可以看到存在这么一个copy to tmp table的操作,证明在后台重建表数据。

修改完成之后查看,发现有个地方不对劲,怎么没有了auto_increment的属性。
> show create table activity_dj_actor_info_log\G
 *************************** 1. row ***************************
        Table: activity_dj_actor_info_log
 Create Table: CREATE TABLE `activity_dj_actor_info_log` (
  `id` bigint(20) NOT NULL DEFAULT '0',
  `cnMaster` varchar(50) NOT NULL,
。。。
  PRIMARY KEY (`id`),
  UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
 1 row in set (0.00 sec)

使用下面的方式修改,让字段id递增,竟然抛出了错误。
> ALTER TABLE activity_dj_actor_info_log modify id  BIGINT AUTO_INCREMENT;
 ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'
就是这个错误让我纠结了半天。
 而且稍后继续尝试,修改auto_increment的值,竟然没有反应。
> ALTER TABLE activity_dj_actor_info_log AUTO_INCREMENT=2147483649;
 Query OK, 3144627 rows affected (1 min 20.65 sec)
 Records: 3144627  Duplicates: 0  Warnings: 0

> show create table activity_dj_actor_info_log\G
 *************************** 1. row ***************************
        Table: activity_dj_actor_info_log
 Create Table: CREATE TABLE `activity_dj_actor_info_log` (
  `id` bigint(20) NOT NULL DEFAULT '0',
  `cnMaster` varchar(50) NOT NULL,
  。。。
  PRIMARY KEY (`id`),
  UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
这问题就很纠结了,修改成功,但是查看表定义没有生效,查看数据字典里的递增序列值还是NULL,证明自增序列没有生效。
> SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name="activity_dj_actor_info_log";
 +----------------+
 | AUTO_INCREMENT |
 +----------------+
 |          NULL |
 +----------------+
 2 rows in set (0.00 sec)
在经过几次尝试之后,最后是采用下面的方式才修复了这个问题。
> alter table `activity_dj_actor_info_log` change `id` `id` bigint  NOT NULL AUTO_INCREMENT , drop primary key,add primary key(id);
 ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'
 > alter table `activity_dj_actor_info_log`  drop primary key;
 Query OK, 3144627 rows affected (1 min 13.75 sec)
 Records: 3144627  Duplicates: 0  Warnings: 0

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/dc911505bca7d95f975268b45d97bc00.html