美文网首页
逻辑删除如何保证数据库记录唯一

逻辑删除如何保证数据库记录唯一

作者: 范柏柏 | 来源:发表于2022-03-14 20:35 被阅读0次
    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='';
    

    需要考虑:

    1. 文件被删除后有可能会再创建一个同名的文件;
    2. 新创建的文件也可能再次被逻辑删除;
    3. 第二个文件被删除后还可能创建第三同名文件,以此类推;
    4. 未删除的文件路径不能有重复值。

    目前来看,因为会逻辑删除,所以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='';
    

    相关文章

      网友评论

          本文标题:逻辑删除如何保证数据库记录唯一

          本文链接:https://www.haomeiwen.com/subject/bapsdrtx.html