软删除与唯一约束共存的解决方案

软删除与唯一约束共存的解决方案

今天一个已经上线了的项目被测出来一个bug,那就是创建了一个用户以后,再把这个用户删了,再创建一个同一个手机号的用户的时候,由于手机号有唯一约束,又用了软删除,就报了手机号码重复的 bug,问题可以简化为:

DROP TABLE IF EXISTS tmp_table;
CREATE TABLE `tmp_table` (
    id bigint primary key auto_increment,
    phone varchar(20) unique not null,
    del_flag int default 0
);

-- 创建一个新用户
INSERT INTO tmp_table (phone) values (15100000000); 

-- 软删除该用户
UPDATE tmp_table SET del_flag = 1 where phone = 15100000000;

-- 创新创建账号
INSERT INTO tmp_table (phone) values (15100000000); 
-- 报错:Duplicate entry '15100000000' for key 'tmp_table.phone'

为了解决这个问题,很容易想到把唯一索引去掉,或者硬删除,但这些都不够优雅。优雅的方式是使用联合约束来进行处理。在有些ORM框架中,软删除是以deleted_at是否为空来做判断的,非空则填上删除时间。这样的话可以在创表的时候创建一个 (phone, deleted_at) 的联合唯一约束,这样就可以解决这个问题了。

DROP TABLE IF EXISTS tmp_table;
CREATE TABLE `tmp_table` (
    id bigint primary key auto_increment,
    phone varchar(20) not null,
    deleted_at timestamp default null
);
ALTER TABLE tmp_tableadd unique key `phone_deleted_at_unique`(`phone`, `deleted_at`);

如果对于一个已经上线了的应用,重新创表不太现实,还是需要进行数据库的迁移,有两种策略,一是替换掉del_flag 软删除改用 deleted_at 软删除的方式,然后添加联合唯一约束,二是再加一个 deleted_at,当要删除一个数据前,先调 update 修改 deleted_at,再删。由于这个项目使用的ORM是Mybatis Plus,目前还没调研怎么替换使用 deleted_at 来进行软删除,所以暂时只是新加了一列 deleted_at 来辅助创建联合唯一约束。数据库迁移步骤如下:

-- 首先删除 phone 的唯一约束
DROP INDEX phone_unique on users;

-- 添加一列 deleted_at
ALTER TABLE tmp_table ADD COLUMN deleted_at timestamp DEFAULT NULL AFTER updated_at;

-- 添加联合唯一约束
ALTER TABLE tmp_table add unique key `users_phone_deleted_at_unique`(`phone`, `deleted_at`);

-- 将已经软删除的数据添加上 deleted_at 的数据
UPDATE tmp_table SET users.deleted_at = users.updated_at where users.del_flag = 1;

这样就可以解决软删除和唯一约束共存时会导致的问题啦,不过这里还留了一个坑待填,那就是 Mybatis plus 怎么用 deleted_at 来进行软删除,这个在后续调研后再写一篇文章。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值