0
点赞
收藏
分享

微信扫一扫

【MySQL报错】FATAL No shared unique key can be found after ALTER!

千行 2022-07-04 阅读 73

最近项目里面的一个数据库,因为前期的业务考虑的不周到,表结构一直在改动。其中一个问题就是主键的选取,本来是ok的,然后业务变的复杂了一点,之前的主键不唯一了,导致大量的用户数据没法被插入。所以提交了两个工单,准备把之前的主键干掉,换成自己新维护的主键,SQL语句如下:

alter table Test add column id int(11) not null first, drop primary key;
alter table Test add primary key(id),change id id bigint not null auto_increment;

当然因为保密原因,我把表名换掉了。逻辑十分的简单,首先添加一列作为备选的主键,然后干掉主键。

mentor看了说线上的数据库不允许没有主键,因为这两个SQL不能同时执行,需要提交工单,获得DBA审批之后,才会由DBA执行。所以如果直接干掉主键,就会有几个小时使得线上的数据库处于没有主键的状态,这在线上是不允许的。所以就改成了:

alter table Test add column id int(11) not null first
alter table Test drop primary key,add primary key(id),change id id bigint not null auto_increment;

然后第二次提交工单的时候报错:**FATAL No shared unique key can be found after ALTER! Bailing out**

去查了一下原因:原来是因为再添加列的时候,其实相当于MySQL把表格重建了一下,然后在这个过程中,它会根据一个Unique key来把把数据一行一行的复制过去,在这个表里面,就是用了主键来做这件事情,然后把主键干掉以后,就没法做这件事情。所以需要添加一个Unique key 让他当做前后两个表的连接桥梁,这个也叫做Share Key。然后干掉主键就可以了。

alter table Test add column id int(11) not null first;
ALTER TABLE Test ADD UNIQUE KEY id_idx(id)
alter table Test drop primary key,add primary key(id),change id id bigint not null auto_increment;

其实这个问题很少会出现,因为有的MySQL数据库没有做这样的限制,但是线上的数据库为了保证安全,常常都有这样的限制。有人可能会问,这么复杂,为啥不把表格干掉重建?因为数据库里面有数据,如果你去备份数据然后干掉再导入,首先线上数据库不允许你直接操作,你需要用代码实现这些,当然也不困难,但是在往数据库里面刷数据的这段时间,用户很有可能访问数据库失败,这样会造成业务失败的可能,这个一般还是不要搞这种事情,很有可能给你个事故通报。

其实更改主键这件事,从SQL上来看,是一件很简单的事情,但是从MySQL底层来看,这里面会发生很大的变化。首先,磁盘上的数据都是按照主键顺序存的,这时肯定会发生变动。然后索引会重构。所以影响还是比较大的。


举报

相关推荐

0 条评论