这个“软删除”有问题吗?使用 EAV 表的解决方案?

发布于 2024-10-25 23:43:45 字数 2539 浏览 3 评论 0原文

我读过一些有关仅在表中设置 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 来处理 行值的未知大小

您是否发现这种类型的软删除存在任何其他明显的问题?

I've read some information about the ugly side of just setting a deleted_at field in your tables to signify a row has been deleted.

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

Are there any potential problems with taking a row from a table you want to delete and pivoting it into some EAV tables?

For instance.

Lets Say I have two tables deleted and deleted_row respectively described as follows.

    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    |                | 
    +--------+--------------+------+-----+---------+----------------+

Now when you wanted to delete a row from any table you would delete it from the table then insert it into these tables as such.

    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. | 
    +----+--------+-------------+-------------------------------+

A few things I see off the bat.

  1. You'll need to use application logic
    to do the pivot (Ruby, PHP, Python,
    etc)
  2. The table could grow pretty big
    because I'm using blob to handle
    the unknown size of the row value

Do you see any other glaring problems with this type of soft delete?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ぃ弥猫深巷。 2024-11-01 23:43:45

为什么不使用存档表来镜像您的表呢?

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)和一个可用于删除已删除(呵呵)行的代理键。

您还可以考虑对deleted_dtm 上的存档表进行范围分区。这使得从表中清除数据变得非常容易。

Why not mirror your tables with archive tables?

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)
)

And then simply add on-delete-triggers on your tables that inserts the current row in the mirrored table before the deletion? That would provide you with dead-simple and very performant solution.

You could actually generate the tables and trigger code using the data dictionary.

Note that I might not want to have a unique index on the original primary key (col_1) in the archive table, because you may actually end up deleting the same row twice over time if you are using natural keys. Unless you plan to hook up the archive tables in your application (for undo purposes) you can drop the index entirely. Also, I added the time of delete (deleted_dtm) and a surrogate key that can be used to delete the deleted (hehe) rows.

You may also consider range partitioning the archive table on deleted_dtm. This makes it pretty much effortless to purge data from the tables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文