V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
mynameisny
V2EX  ›  问与答

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

  •  
  •   mynameisny · Nov 29, 2017 · 17963 views
    This topic created in 3077 days ago, the information mentioned may be changed or developed.

    铺垫

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

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

    感谢 @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  
       Nov 30, 2017
    移表......
    jjianwen68
        29
    jjianwen68  
       Nov 30, 2017
    一些绑定关系啊之类数据倒是可以直接删除,大部分应该都是软删除。如果说时间长数据太多,可以分当前表、历史表,业务允许可以定期删除半年或一年之前的数据
    Zephyros
        30
    Zephyros  
       Nov 30, 2017
    删除时移动到其他表保存一个月,一个月后再彻底删除。这样就不会拖慢查询速度了。

    不然,比方说你告诉用户有销号功能,但又销不掉,这个会令用户不爽。我还希望把保护用户隐私写入宪法呢,这辈子都不知有没有戏。
    18583826786
        31
    18583826786  
       Nov 30, 2017 via Android
    一般应该是有一个字段,判断这一条数据还有没有用,并不是真删
    ixiaohei
        32
    ixiaohei  
       Nov 30, 2017
    软删除的很好奇你们唯一键都是怎么玩的。另外索引都要加上那一列表示删除的字段么?
    bk201
        33
    bk201  
       Nov 30, 2017
    个人感觉打标记软删除没啥好处,不如移出当前表
    loveminds
        34
    loveminds  
       Dec 4, 2017
    删除之前 dump 出来备份,有备无患
    ruandao
        35
    ruandao  
       Nov 18, 2019
    @ixiaohei 唯一键不都是业务无关的吗?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2532 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 105ms · UTC 09:01 · PVG 17:01 · LAX 02:01 · JFK 05:01
    ♥ Do have faith in what you're doing.