使用EAV表的“软删除”解决方案是否存在问题?

时间:2011-03-23 16:53:58

标签: sql database-design delete-row

我已经阅读了一些关于在表格中设置deleted_at字段以表示某行已被删除的丑陋方面的信息。


http://richarddingwall.name/2009/11/20/the-trouble-with-soft-delete/

从要删除的表中取一行并将其转换为某些EAV表是否存在任何潜在问题?

例如。

让我说我有两个表deleteddeleted_row分别描述如下。

    mysql> describe deleted;
    +------------+--------------+------+-----+---------+----------------+
    | Field      | Type         | Null | Key | Default | Extra          |
    +------------+--------------+------+-----+---------+----------------+
    | id         | int(11)      | NO   | PRI | NULL    | auto_increment | 
    | tablename  | varchar(255) | YES  |     | NULL    |                | 
    | deleted_at | timestamp    | YES  |     | NULL    |                | 
    +------------+--------------+------+-----+---------+----------------+

    mysql> describe deleted_rows;
    +--------+--------------+------+-----+---------+----------------+
    | Field  | Type         | Null | Key | Default | Extra          |
    +--------+--------------+------+-----+---------+----------------+
    | id     | int(11)      | NO   | PRI | NULL    | auto_increment | 
    | entity | int(11)      | YES  | MUL | NULL    |                | 
    | name   | varchar(255) | YES  |     | NULL    |                | 
    | value  | blob         | YES  |     | NULL    |                | 
    +--------+--------------+------+-----+---------+----------------+

现在,当您想从任何表中删除一行时,您将从表中删除它,然后将其插入这些表中。

    deleted
    +----+-----------+---------------------+
    | id | tablename | deleted_at          |
    +----+-----------+---------------------+
    |  1 | products  | 2011-03-23 00:00:00 | 
    +----+-----------+---------------------+

    deleted_row
    +----+--------+-------------+-------------------------------+
    | id | entity | name        | value                         |
    +----+--------+-------------+-------------------------------+
    |  1 |      1 | Title       | A Great Product               | 
    |  2 |      1 | Price       | 55.00                         | 
    |  3 |      1 | Description | You guessed it... it's great. | 
    +----+--------+-------------+-------------------------------+

我看到的一些事情。

  1. 您需要使用应用程序逻辑 做角色(Ruby,PHP,Python, 等)
  2. 桌子可能会变得很大 因为我正在使用blob来处理 行值的未知大小
  3. 您是否看到此类软删除存在其他明显问题?

1 个答案:

答案 0 :(得分:1)

为什么不用存档表镜像表?

create table mytable(
   col_1 int
  ,col_2 varchar(100)
  ,col_3 date 
  ,primary key(col_1)
)

create table mytable_deleted(
   delete_id  int      not null auto_increment
  ,delete_dtm datetime not null
-- All of the original columns
  ,col_1 int
  ,col_2 varchar(100)
  ,col_3 date 
  ,index(col_1)
  ,primary key(delete_id)
)

然后只需在表上添加on-delete-triggers,在删除之前在镜像表中插入当前行?这将为您提供简单且非常高效的解决方案。

您实际上可以使用数据字典生成表格和触发代码。

请注意,我可能不希望在归档表中的原始主键(col_1)上具有唯一索引,因为如果使用自然键,实际上最终可能会在一段时间内删除同一行两次。除非您计划在应用程序中连接存档表(出于撤消目的),否则可以完全删除索引。此外,我添加了删除时间(deleted_dtm)和可用于删除已删除(hehe)行的代理键。

您还可以考虑在deleted_dtm上对归档表进行范围分区。这使得从表中清除数据非常轻松。