V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
mynameisny
V2EX  ›  问与答

炒冷饭,对于数据库“删除”操作大家平时都是物理删除,还是逻辑删除啊?

  •  
  •   mynameisny · 2017-11-29 19:37:46 +08:00 · 17148 次点击
    这是一个创建于 2581 天前的主题,其中的信息可能已经有所发展或是发生改变。

    铺垫

    本人不才,不知这个“逻辑删除”词用的对不对,想表达的就是:当删除时只是将 is_deleted 字段设置为 1,而不是真的将这条记录删掉,关键词可能是 logic delete 或 soft delete。


    问题

    • 查了一些资料,貌似支持“逻辑删除”观点的人是多数的:

      • 有前辈提到一个观点,真实世界是没有删除的。订单作废,用户禁用,员工离职,文稿废弃,优惠券作废都是状态的变化。所以 SQL 里面 DELETE 在业务场景里都不应该出现。

      • 为了安全,生产环境不能有人或有程序是对数据库的表有 DELETE 权限的。

    • 反对的声音还是有的:

      • 逻辑删除的设计还会导致常用的 unique key 失效(当然用户可将数据行中原来的码和 is_deleted 一起作为 unique key,但是这样又会出现,再次删除时,系统中无法出现两个完全相同的 ID,又都是 is_deleted=1 的记录出现)。

      • 被“删除”的这条记录如果在业务中与大量的表有关联关系,那么在删除它时,就会引发很多的级联的更新,或者判断引用并提示用户无法修改正被引用的资源。而要保证这些全部更新无误,又要求事务一定可靠,若产生了状态不一致,那么这些“脏数据”的维护也是很痛苦的。

      • 当表中的记录数越来越大时,查询起来会越来越慢。


    求解

    我能理解具体问题需要具体分析,是要“逻辑删除”还是“物理删除”,主要还是要根据实际的业务场景,比如互联网企业搜 /收集的个人信息、电商类平台用户的订单、金融类平台的交易记录,肯定是不能删除的。但是对于一些维护中间状态的数据,如果可以通过记录日志实现“留档”那么就可以真的删掉它。

    不知道有没有那种开源组件,可以_自动实现_当我从一个表中物理删除一条记录时,它可以帮我将它转移到备份表中,我看了一个 MySQL 的审计插件,但是好像并不做这个用途的。或者有类似“ commit log ”那种东东,删除时只需要记录一个 log,有需要的时候可以从日志中恢复回来。


    参考

    下附几个我搜过的资料,希望能帮助和我一样迷茫的童鞋:

    1. “别删除数据” http://www.infoq.com/cn/news/2009/09/Do-Not-Delete-Data

    2. “逻辑删除真的不是一个好的设计 - 简书” http://www.jianshu.com/p/f37281576585

    3. “ MySQL 删除数据是加一个字段做标记,还是将删除的数据插入到另外一张备份表里,哪种方案更好? - V2EX ” https://fast.v2ex.com/t/406208

    4. “不做显式删除,而用 status=0 代替,是好的实践么? - V2EX ” https://www.v2ex.com/t/363226

    35 条回复    2019-11-18 19:03:36 +08:00
    BOYPT
        1
    BOYPT  
       2017-11-29 19:46:00 +08:00   ❤️ 4
    物理删除?是指那硬盘去用铝热剂烧吗
    swuzjb
        2
    swuzjb  
       2017-11-29 19:46:24 +08:00
    看业务
    zn
        3
    zn  
       2017-11-29 19:57:51 +08:00 via iPhone
    基本都是标志删除。做事要留后悔药。
    msg7086
        4
    msg7086  
       2017-11-29 20:22:33 +08:00
    如果真实世界没有删除,那真实世界也就没有新建了。宇宙的能量是守恒的。
    wingoo
        5
    wingoo  
       2017-11-29 20:27:40 +08:00
    没有真实删除的
    liprais
        6
    liprais  
       2017-11-29 20:35:08 +08:00 via iPhone
    真删了还分析啥
    p2pCoder
        7
    p2pCoder  
       2017-11-29 20:41:04 +08:00 via Android
    现在还有物理删除的?
    R18
        8
    R18  
       2017-11-29 20:44:38 +08:00 via Android
    当然有物理删除啊,我们每天几 G 日志用 mysql 存,基本就是分析一次,最多更新三次,查一个月以内,这些数据不删除存着干嘛…
    ratazzi
        9
    ratazzi  
       2017-11-29 20:51:49 +08:00 via iPhone
    unique key 的问题用 PostgreSQL 的 partial index 不错
    Jackeriss
        10
    Jackeriss  
       2017-11-29 20:53:38 +08:00
    @BOYPT 化学删除:将硬盘浸入浓硫酸。
    billlee
        11
    billlee  
       2017-11-29 21:15:10 +08:00
    物理删除。回滚靠 binlog.
    gamexg
        12
    gamexg  
       2017-11-29 21:27:51 +08:00 via Android
    >逻辑删除的设计还会导致常用的 unique key 失效(当然用户可将数据行中原来的码和 is_deleted 一起作为 unique key,但是这样又会出现,再次删除时,系统中无法出现两个完全相同的 ID,又都是 is_deleted=1 的记录出现)。

    is_deleted 记录删除时间戳即可。
    p2pCoder
        13
    p2pCoder  
       2017-11-29 21:38:21 +08:00
    @R18 建模数据维度越多,以后可选择的空间越大,有大数据和 AI 考虑的,还是可以保留,不过,不用一直保存在 mysql 中
    Tink
        14
    Tink  
       2017-11-29 21:49:43 +08:00 via iPhone
    还有物理删除的?
    LemonFlower
        15
    LemonFlower  
       2017-11-30 01:28:34 +08:00 via iPhone
    外包项目是真删除,公司项目是打标记,还是看需求啦....如果没有要求,更喜欢真实删除数据,不喜欢被欺骗,所以也不想欺骗别人
    falcon05
        16
    falcon05  
       2017-11-30 04:46:48 +08:00 via iPhone
    看业务,大部分场景不能做物理删除,以前公司招了个逼,用户删除订单,就真的从数据库里删除了……惊呆了
    Mutoo
        17
    Mutoo  
       2017-11-30 06:17:55 +08:00
    这个术语叫 soft delete (软删除)
    cnTangLang
        18
    cnTangLang  
       2017-11-30 06:31:55 +08:00 via Android
    正常的商业系统,都必须软删除
    当然不一定只是做标记,也可能用移表的方法啊。
    jydeng
        19
    jydeng  
       2017-11-30 08:11:19 +08:00
    一般都是软删除,做人留一线
    shakoon
        20
    shakoon  
       2017-11-30 08:21:52 +08:00
    在我司,delete 是高级权限操作,任何含 delete 的代码上线前必须经过若干领导冗长的评审,楼主感受一下 →_←
    Perry
        21
    Perry  
       2017-11-30 08:30:35 +08:00
    硬删除,公司规定。
    l00t
        22
    l00t  
       2017-11-30 09:37:04 +08:00
    unique key 失效?你们这数据库都怎么做设计的,这都还能失效?
    linxl
        23
    linxl  
       2017-11-30 09:38:59 +08:00
    软删除
    nl101531
        24
    nl101531  
       2017-11-30 10:02:38 +08:00
    逻辑删
    pypy
        25
    pypy  
       2017-11-30 10:06:29 +08:00
    逻辑删除啊。数据都是钱啊,你不要的数据可以给我。(开个小玩笑)
    zpf124
        26
    zpf124  
       2017-11-30 10:13:43 +08:00
    小部门小规模,删除几乎都是数据库直接删除。
    mynameisny
        27
    mynameisny  
    OP
       2017-11-30 14:54:17 +08:00
    得到了很多前辈的实操经验,也收获了几条实际的解决方案。

    感谢 @gamexg 的方案:使用 is_deleted 字段记录“删除”时刻的时间戳,再将主键与 is_deleted 作为 unique key,有点小问题就是 is_deleted 这个字段的默认值必须是一个非 NULL 的值,否则 name + NULL 的组合,即使 name 不同,也不能被视为一条唯一值。

    感谢 @billlee 的方案,不知道有 binlog 这个运维工具(开眼界 : P ),mysql 的 bin 目录提供了 mysqlbinlog 工具。

    partial index 是头一回听说(开眼界),移表的方案也很好,不过有点担心当表定义比较多时会造成每张表都有一张“回收站”表。

    感谢其他 V 友们的回复!
    openbsd
        28
    openbsd  
       2017-11-30 15:05:38 +08:00
    移表......
    jjianwen68
        29
    jjianwen68  
       2017-11-30 15:21:36 +08:00
    一些绑定关系啊之类数据倒是可以直接删除,大部分应该都是软删除。如果说时间长数据太多,可以分当前表、历史表,业务允许可以定期删除半年或一年之前的数据
    Zephyros
        30
    Zephyros  
       2017-11-30 16:58:09 +08:00
    删除时移动到其他表保存一个月,一个月后再彻底删除。这样就不会拖慢查询速度了。

    不然,比方说你告诉用户有销号功能,但又销不掉,这个会令用户不爽。我还希望把保护用户隐私写入宪法呢,这辈子都不知有没有戏。
    18583826786
        31
    18583826786  
       2017-11-30 17:13:14 +08:00 via Android
    一般应该是有一个字段,判断这一条数据还有没有用,并不是真删
    ixiaohei
        32
    ixiaohei  
       2017-11-30 17:17:52 +08:00
    软删除的很好奇你们唯一键都是怎么玩的。另外索引都要加上那一列表示删除的字段么?
    bk201
        33
    bk201  
       2017-11-30 17:30:43 +08:00
    个人感觉打标记软删除没啥好处,不如移出当前表
    loveminds
        34
    loveminds  
       2017-12-04 08:13:36 +08:00
    删除之前 dump 出来备份,有备无患
    ruandao
        35
    ruandao  
       2019-11-18 19:03:36 +08:00
    @ixiaohei 唯一键不都是业务无关的吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3270 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:07 · PVG 20:07 · LAX 04:07 · JFK 07:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.