Rails 7中如何将非确定性加密列迁移为确定性加密列?
ActiveRecord非确定性加密列迁移方案
迁移为确定性加密列
直接修改deterministic: true仅对新数据生效,现有非确定性加密数据无法被新逻辑识别,需通过数据迁移完成转换:
添加临时加密列
生成迁移文件添加临时列,同时在模型中配置其为确定性加密:# 迁移文件:rails generate migration AddTempEncryptedAttrToYourModels temp_encrypted_attr:string class AddTempEncryptedAttrToYourModels < ActiveRecord::Migration[7.0] def change add_column :your_models, :temp_encrypted_attr, :string end end模型配置:
class YourModel < ApplicationRecord encrypts :attr, deterministic: false # 原非确定性加密列 encrypts :temp_encrypted_attr, deterministic: true, key: Rails.application.credentials.active_record_encryption[:key] end批量转换数据
用分批处理脚本解密原列数据,再通过临时列的确定性加密逻辑重新存储:# 可通过rails runner执行该脚本 YourModel.find_each(batch_size: 1000) do |record| next if record.attr.nil? record.temp_encrypted_attr = record.attr record.save!(validate: false) # 跳过验证提升效率,需确保数据本身合法 end验证数据一致性
随机抽查数据,确认原列解密后与临时列解密后的值完全一致:sample_records = YourModel.sample(15) sample_records.each do |r| puts "数据匹配:#{r.attr == r.temp_encrypted_attr}" end替换原列
生成迁移文件删除原加密列,将临时列重命名为原列名,最后更新模型配置:# 迁移文件:rails generate migration ReplaceEncryptedAttrColumn class ReplaceEncryptedAttrColumn < ActiveRecord::Migration[7.0] def change remove_column :your_models, :encrypted_attr # 注意ActiveRecord自动添加的encrypted_前缀 rename_column :your_models, :temp_encrypted_attr, :encrypted_attr end end最终模型配置:
class YourModel < ApplicationRecord encrypts :attr, deterministic: true end
完全移除加密列
若无需保留加密,步骤类似,临时列存储明文数据:
添加明文临时列
生成迁移文件添加与原属性类型一致的明文列:# 迁移文件:rails generate migration AddTempAttrToYourModels temp_attr:string class AddTempAttrToYourModels < ActiveRecord::Migration[7.0] def change add_column :your_models, :temp_attr, :string # 类型需与原attr匹配 end end批量解密写入明文列
分批处理数据,将原加密列解密后写入临时列:YourModel.find_each(batch_size: 1000) do |record| next if record.attr.nil? record.temp_attr = record.attr record.save!(validate: false) end验证数据正确性
抽查确认临时列的值与原列解密后完全一致。替换并清理
生成迁移文件删除原加密列,重命名临时列为原列名,最后移除模型中的加密配置:# 迁移文件:rails generate migration RemoveEncryptionFromAttr class RemoveEncryptionFromAttr < ActiveRecord::Migration[7.0] def change remove_column :your_models, :encrypted_attr rename_column :your_models, :temp_attr, :attr end end
注意事项
- 操作前必须备份数据库,防止数据丢失
- 选择业务低峰期执行批量操作,降低对服务的影响
- 根据服务器性能调整batch_size,避免内存占用过高
- 先在测试环境完整走一遍流程,验证无误后再部署到生产环境
内容的提问来源于stack exchange,提问作者Mitchell
相关产品推荐
相关产品推荐

