CREATE TABLE `t_file` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`shop_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'shop_id',
`file_url` int unsigned NOT NULL DEFAULT '0' COMMENT '文件链接',
`is_delete` int unsigned NOT NULL DEFAULT '0' COMMENT '是否删除,0-否 1-是',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='';
需要考虑:
- 文件被删除后有可能会再创建一个同名的文件;
- 新创建的文件也可能再次被逻辑删除;
- 第二个文件被删除后还可能创建第三同名文件,以此类推;
- 未删除的文件路径不能有重复值。
目前来看,因为会逻辑删除,所以shop_id + is_delete不能加唯一索引被删除的会重复。
一、加字段保证行的唯一性
CREATE TABLE `t_file` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`shop_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'shop_id',
`file_url` int unsigned NOT NULL DEFAULT '0' COMMENT '文件链接',
`is_delete` int unsigned NOT NULL DEFAULT '0' COMMENT '是否删除,0-否 1-是',
`delete_time` int unsigned NOT NULL DEFAULT '0' COMMENT '删除时间,0表示未删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_shop_id_file` (`shop_id`, `file_url`, `is_delete`, `delete_time`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='';
加上delete_time字段。
建shop_id + file_url + is_delete + delete_time唯一索引。
删除行,同时赋值delete_time。这样删除行就不会冲突了。
新增行,is_delete和delete_time都是0。唯一索引也能保证只会有一条数据。
二、分布式锁
redis分布式锁有天然的问题。不做考虑(可以参考我的另一片文章分布式锁)。
所以,就使用mysql锁。
锁粒度可以为店铺粒度。唯一索引为shopId。
CREATE TABLE `t_file_lock` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`shop_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'shop_id',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_shop_id` (`shop_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='';
每次更新数据前,先锁shopId这个实体。再执行insert 或 update。
锁粒度也可以为店铺+文件粒度。唯一索引为shop_id+file_url。
CREATE TABLE `t_file_lock` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`shop_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'shop_id',
`file_url` int unsigned NOT NULL DEFAULT '0' COMMENT '文件链接',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_shop_id_file` (`shop_id`, `file_url`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='';
每次更新数据前,先锁shop_id + file_url这个实体。再执行insert 或 update。
三、对实体做更新不做重新插入
当被删除的数据,再次被添加时,不做插入操作,直接更新原记录到正常状态。此时原表可以加唯一索引。
CREATE TABLE `t_file` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`shop_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'shop_id',
`file_url` int unsigned NOT NULL DEFAULT '0' COMMENT '文件链接',
`is_delete` int unsigned NOT NULL DEFAULT '0' COMMENT '是否删除,0-否 1-是',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_shop_id_file` (`shop_id`, `file_url`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='';
这个时候操作历史就丢了,怎么办呢。新加一张表,专门用来记录变更流水。
CREATE TABLE `t_file_record` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`shop_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'shop_id',
`file_url` int unsigned NOT NULL DEFAULT '0' COMMENT '文件链接',
`operate` varchar(64) NOT NULL DEFAULT '0' COMMENT '操作 insert or delete',
`remark` varchar(1024) NOT NULL DEFAULT '0' COMMENT '操作备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='';
网友评论