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

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 昨天快下班的时候,突然开发的同事找我说有个紧急需求,负责这个业务的DBA同事回家了,想让我帮忙看看,运行个SQL语句,几秒钟就好。我一听,就本着人道主义的精神留下来处理,但是发现似乎留给我的是一个大坑。
昨天快下班的时候,突然开发的同事找我说有个紧急需求,负责这个业务的DBA同事回家了,想让我帮忙看看,运行个SQL语句,几秒钟就好。我一听,就本着人道主义的精神留下来处理,但是发现似乎留给我的是一个大坑。
了解了问题之后,让我有些后背发凉,这个表根据开发同事反馈有20亿的数据,这得多大的一个表啊,当前的问题是这个表里的主键id数据类型是int,因为数据类型的限制已经达到了最大值,现在插入不了数据了。希望我帮忙处理一下,把数据类型修改为bigint.
我们简单来了解一下MySQL的数据类型。
对于数据类型有下面的一些总结,更详细可以参见之前写的一篇。http://blog.itpub.net/23718752/viewspace-1371434/
类型 大小 范围(有符号) 范围(无符号) 用途
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

> alter table `activity_dj_actor_info_log` change `id` `id` bigint  NOT NULL AUTO_INCREMENT , add primary key(id);
Query OK, 3144627 rows affected (1 min 32.32 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 AUTO_INCREMENT,
  `cnMaster` varchar(50) NOT NULL,
  。。。
  PRIMARY KEY (`id`),
  UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2150192178 DEFAULT CHARSET=utf8
和开发的同事简单沟通之后,没过一会查看就发现数值是递增了。
> select max(id) from activity_dj_actor_info_log;
+------------+
| max(id)    |
+------------+
| 2150195418 |
+------------+
而对于这个问题,自己也简单总结了下,其实最开始处理的时候就不严谨,导致了后面的不断修复,如果一步到位就不会有这么多的麻烦了。
所以在本地有简单测试了下。

CREATE TABLE `activity_dj_actor_info_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cnMaster` varchar(50) NOT NULL,
。。。
  PRIMARY KEY (`id`),
  UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8;
插入一部分测试数据。
> insert into activity_dj_actor_info_log select *from activity_log.activity_dj_actor_info_log limit 1,1000;
Query OK, 1000 rows affected (0.07 sec)
Records: 1000  Duplicates: 0  Warnings: 0
修改表字段数据类型
> alter table activity_dj_actor_info_log modify  `id` bigint  NOT NULL AUTO_INCREMENT;
Query OK, 1000 rows affected (0.43 sec)
Records: 1000  Duplicates: 0  Warnings: 0
再次查看递增序列就修改完善了。
> show create table activity_dj_actor_info_log;
| Table                      | Create Table      
| activity_dj_actor_info_log | CREATE TABLE `activity_dj_actor_info_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `cnMaster` varchar(50) NOT NULL,
  。。。
  PRIMARY KEY (`id`),
  UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
在这一点上,Oracle的处理和MySQL还是存在一些区别,还是需要严格区别对待。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
存储 关系型数据库 MySQL
MySQL数据类型详解及实例应用
MySQL数据类型详解及实例应用
|
存储 关系型数据库 MySQL
MySQL数据库的数据类型、语法和高级查询
MySQL数据库的数据类型、语法和高级查询
215 0
|
SQL 存储 关系型数据库
RDS for MySQL的SQL分类与数据类型
小明需在MySQL中管理商品信息,使用SQL完成业务操作。SQL分为DQL(查询)、DML(增删改)、DDL(定义)、DCL(权限控制)和TCL(事务)五大类。DDL用于创建、修改和删除数据库结构,DML处理数据,DCL控制权限,TCL管理事务,DQL则用于查询数据。MySQL有多种数据类型,如数值型(整数、小数)、日期型和字符串型等,选择合适的数据类型是高效开发的关键。
270 0
|
关系型数据库 MySQL 数据库
MySQL数据库基础(数据库操作,常用数据类型,表的操作)
MySQL数据库基础(数据库操作,常用数据类型,表的操作)
193 5
|
存储 关系型数据库 MySQL
MySQL支持多种数据类型
MySQL支持多种数据类型
335 4
|
存储 关系型数据库 MySQL
MySQL数据类型
MySQL数据类型
172 3
|
存储 关系型数据库 MySQL
什么是mysql的数据类型?
什么是mysql的数据类型?
194 2
|
存储 关系型数据库 MySQL
|
关系型数据库 MySQL Linux
数据类型和运算符(MySQL服务器的安装,MySQL客户端,数据类型,运算符,MySQL的语法规范)
无论是对于初学者还是有经验的开发者,了解MySQL的安装、客户端使用、数据类型、运算符和语法规范都是至关重要的。这不仅有助于高效地管理和查询数据,而且对于设计和实现数据库解决方案来说是基础工作。通过深入学习和实践这些知识,您可以更好地发挥MySQL数据库的强大功能。
135 2
|
存储 关系型数据库 MySQL
MySQL 中的 BLOB 数据类型深入解析
【8月更文挑战第31天】
2465 0

推荐镜像

更多