Rails应用中如何克隆无数据表并保持表结构同步?
Rails 软删除归档表实现方案
1. 一次性克隆结构一致的空表
直接用数据库原生语句创建同结构空表,可以完整保留原表的字段类型、索引、非空约束等所有属性,比手动复制迁移字段准确性更高。
创建新迁移文件执行以下逻辑:
# 假设原表名为 products,归档表名为 archived_products class CreateArchivedProducts < ActiveRecord::Migration[7.0] def change # 克隆表结构,不复制原表数据 execute "CREATE TABLE archived_products LIKE products;" # 如果需要重置归档表自增主键起始值可执行下面的语句,要保留原记录主键的话跳过即可 # execute "ALTER TABLE archived_products AUTO_INCREMENT = 1;" end end
2. 自动同步两张表结构,无需重复写迁移
通过封装通用同步方法,所有对原表的结构变更可以自动同步到归档表:
- 先封装同步工具模块
# lib/archived_table_sync.rb module ArchivedTableSync # 同时对原表和归档表执行结构变更 def sync_schema(original_table, archive_table, &operation) [original_table, archive_table].each do |table| yield(table) end end end
- 后续所有涉及原表结构变更的迁移,直接引入模块调用方法即可
# 示例:给products表加discount字段,自动同步到归档表 class AddDiscountToProducts < ActiveRecord::Migration[7.0] include ArchivedTableSync def change sync_schema(:products, :archived_products) do |table| table.decimal :discount, default: 0.0, null: false end # 加索引也可以用同样的方法同步 # add_index :products, :discount # add_index :archived_products, :discount end end
3. 模型复用,无需重复编写业务逻辑
归档表的模型直接继承原表模型,即可完整复用所有字段定义、验证规则、关联关系、业务方法,只需要单独指定表名即可:
# app/models/archived_product.rb class ArchivedProduct < Product self.table_name = "archived_products" # 归档表存储的都是已删除数据,不需要再开启`act_as_paranoid`软删除逻辑 self.paranoid = false end
如果有归档表专属的逻辑,直接在ArchivedProduct类中重写对应方法即可。
4. 软删除数据迁移逻辑
为了避免大表操作锁表影响线上业务,建议分批迁移软删除数据,可以写定时Rake任务执行:
# lib/tasks/archive_products.rake namespace :products do desc "批量归档已软删除的商品数据" task archive: :environment do # 每次处理1000条,控制锁表时间和内存占用 Product.only_deleted.in_batches(of: 1000) do |deleted_batch| # 批量插入归档表,保留原记录所有属性 ArchivedProduct.insert_all(deleted_batch.as_json) # 硬删除原表已归档的数据,*不要用destroy,避免触发不必要的回调* deleted_batch.delete_all end end end
如果需要实时归档,可以给原模型加软删除回调,每次执行软删除操作时直接同步到归档表。
注意事项
- 如果原表存在外键约束,创建归档表时建议先移除外键,避免同步结构时出现关联冲突
- 首次全量归档建议放在业务低峰期执行,避免影响正常读写请求
- 后续统计需求直接查询
ArchivedProduct模型即可,不需要再查询原表的软删除数据
内容的提问来源于stack exchange,提问作者Meliborn
相关产品推荐
相关产品推荐

