mysql原生在线DDL修改主键操作的最佳实践

时间:2021-10-23 13:44:37

有一个项目,数据库使用mysql mariadb 10.1.11版本,系统开发是交给外包公司,发现在测试和验证环境所有表都是用varchar型的非自增字段作为主键,如下所示:
      Table: w_t_p
Create Table: CREATE TABLE `w_t_p` (
  `id` varchar(40) NOT NULL COMMENT '主键',
+--------------------------------------+
| id                                   |
+--------------------------------------+
| 3f573f41-3c5c-4e0b-94f4-20785dc6e402 |
| 4f78eb50-b476-43d9-a4da-50f09ecbe057 |
| 6425942e-27ba-4ae6-abda-79e632c75c25 |
+--------------------------------------+

如果不用自增数字键作为主键,会有什么问题呢?
问题很大,主要有如下:
1. 表容易产生碎片,由于碎片的存在,表会变得很大,严重影响查询和DML操作性能
2. 由于主键不是自增的,数据将不会按顺序插入,需要查找合适位置随机插入,严重影响数据插入性能。
3. 主键用uuid值要比用自增数字值所占空间大,同样二级索引也变大,使得用主键或二级索引来查询数据效率相对变低。
强建要求开发人员将主键改为自增数字主键,但要怎么去修改比较好呢?作为DBA,这时需要给出一个比较好的简单的方案给开发人员参考。
于是,DBA动手实验如下:(网上查找各种信息,难以见到有类似方法)
建立相同数据的表:
dba@192.168.1.20;create table g_o_test as select * from g_o;
ERROR 1173 (42000): This table type requires a primary key
关闭主键强制特性:
set global  innodb_force_primary_key=off;
create table g_o_test as select * from g_o;
删除_id字段和修改id字段为为主键:
alter table g_o_test drop column `_id`,modify column `id` varchar(50) NOT NULL COMMENT '主键:系统自动生成' primary key;
show create table g_o_test\G
     Table: g_o_test
Create Table: CREATE TABLE `g_o_test` (
  `id` varchar(50) NOT NULL COMMENT '主键:系统自动生成',
............................
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
开启主键强制特性:
set global  innodb_force_primary_key=on;
show global variables like 'innodb_force_primary_key';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_force_primary_key | ON    |
dba@10.16.74.60:3306(db(master)) : midea_gls_ver 09:17:49>alter table g_o_test drop primary key,add unique key (`id`);
Query OK, 0 rows affected (42.33 sec)               
Records: 0  Duplicates: 0  Warnings: 0
dba@10.16.74.60:3306(db(master)) : midea_gls_ver 09:29:10>alter table g_o_test add column `_id` int not null auto_increment primary key comment '主键' first;
Query OK, 0 rows affected (29.15 sec)               
Records: 0  Duplicates: 0  Warnings: 0
这样也没有报错,看起来在开启innodb_force_primary_key的情况下,上面操作修改主键也是可以的,但最好方法是:
一个ddl将drop主键、增加唯一键、修改字段、增加主键四个操作合在一起完成:
alter table g_o_test drop primary key,add unique key (`id`),modify column `id` varchar(50) NOT NULL COMMENT '',add column `_id` int not null auto_increment primary key comment '主键' first;
show create table g_o_test\G
*************************** 1. row ***************************
       Table: g_o_test
Create Table: CREATE TABLE `g_o_test` (
  `_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `id` varchar(50) NOT NULL COMMENT '',
......................................
  PRIMARY KEY (`_id`),
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=423585 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)