MySQL 删除注意事项
没有删除能力的数据库应用程序是不完整的。然而,典型的开发工作流程往往更加关注记录的创建和更新。毕竟,删除就像挥手解雇一样简单,不是吗?即使没有参照完整性和数据保留考虑,删除也值得更多的工程关注。
删除是必要的
冒着听起来我们正在制造要解决的问题的风险,我们需要删除更多内容,并处理随之而来的并发症。
用户发起的删除是 CRUD(创建、读取、更新和删除)中的 D。它是我们经常不情愿地投入的最后一英里功能。当一个记录可以创建和删除时,它就有一个完整的生命周期。
还有另一种删除方式——“定期清除”。必须释放临时表,应删除超出用户同意保留期限的记录。哎呀,为了存储和性能,我们应该通过建议更短的保留期来主动保护用户的隐私。
正如人们通常会指出的那样,“但存储很便宜”。这并不完全正确。我们正在关注数据的无限增长。如果 100 Giga Bytes 很便宜,那么 100 Tera Bytes 会一样便宜吗?还是 100 Peta 字节?当有更多数据时,处理器需求呈指数增长。为了让处理器有效地处理磁盘数据,我们还需要更多的 RAM。CPU 和 RAM 并不便宜。
设置上限需要在记录保存策略、数据存储布局和清理巡逻节奏之间保持一致。如果系统的设计者注意限制增长,这种一致性很容易实现。请记住,系统的架构反映了其制造者的思想。
删除是浪费
这是回收与重用的经典论点。删除数据会释放空间,但在具有自动递增 ID 的 MySQL 表中,ID 空间仍然会用完。删除记录不会恢复 ID 是有充分理由的。自动增量 ID 保证记录的标识始终是唯一的。
对时间敏感的服务器端令牌是 ID 回收的良好候选者。例如,我们的实时聊天系统 GS Chat 会向每个来访的客户发出一个自动 ID。如果没有发起聊天,则 ID 进入休眠状态。由于聊天会话 ID 是通过时间认证的,并且聊天客户端会主动使长时间的空闲会话无效,因此重复使用的 ID 不会造成任何混淆。
通常,ID 重用需要仔细规划和编排一些移动组件。正确完成后,ID 空间节省非常显着。
删除是昂贵的
如果您使用 MySQL 的 InnoDB 存储引擎,这很可能是这种情况,删除记录的性能成本可能会让人感到意外。在唯一列是主键的简单表上,删除除 1500 万条记录之外的所有记录可能需要一分钟!日期长度只有 60 MB,那么为什么要花这么长时间才能减少 60 MB?
这是因为 InnoDB 在删除时会重新组织数据。当许多记录被删除时,“重新分区”表的工作需要指数级的时间。更糟糕的是,删除记录是一种明显的行级操作,现在被提升到表级。当删除和数据库导出(mysqldump)同时发生时,数据库将被锁定很长时间。
我们可以通过两种方式减轻对性能的影响:
首先,限制受影响记录的传播。将删除分成更小的批次。在数据巡查的情况下,增加频率并减少批量大小。
其次,降低磁盘 I/O 成本。这涉及调整 trx 提交级别和缓冲池大小。
另一个促成因素是复制。在主从设置中,data_length(在 information_schema.tables 中轮询)不会立即减少。只有当 binlog 赶上时才会释放空间。进行数据转储时,强烈建议仅从只读副本(从属)导出。
关键要点
限制数据增长
尽可能回收记录
通过分块、锁避免和 I/O 优化降低删除性能损失