记一次批量处理数据库中的敏感信息

前言

对于一些敏感数据,往往会对其加密后再入库,这个是对数据安全性的一个最为简单的措施。

最常见的莫过于手机号码和身份证号了,相信还是有不少公司对这些敏感信息是明文存储的。

万一被别人发现系统漏洞,或者是被拖库,那基本上就凉凉了。

老黄最近也是发现了公司内部一个系统有这样的问题,刚发现的时候都吓了我一跳,这么赤裸裸的明文手机号和身份证号。

第一反应就是要把这两个数据进行加密处理。

既然要加密处理,那么正在使用的系统肯定就会受到影响,而且几千万数据,也不是几分钟就能搞定的。

这个系统用的数据库是阿里云的RDS(SQL Server)。

下面简单说一下老黄这边的处理方案。

如何处理

整个处理的流程是分了三个步骤:

  1. 修改数据库中的字段长度
  2. 系统要更新一个版本做兼容处理,写入要用统一的加密方法,读取的时候,要加一个长度判断,当长度大于20的时候,需要进行解密操作,这样才能确保不会把密文直接展示出去。
  3. 修改数据

之前数据库给这两个字段设置的长度都是20,现在统一调整成150。

公司内部已经统一了一套加解密方法了,所以系统调整这一块是比较简单的,统一在数据层处理。

剩下的就是去数据库改数据了。

统一的加密方法,在数据库中没有办法直接使用,所以只能单独写个程序去处理。

改数据也细分为下面3步。

  1. 读取源数据,加密相关字段
  2. 将加密的数据写入到一张临时表中
  3. 根据临时表去更新源表的相关字段

这里的最为核心的一个就是批量写入批量更新。如果一条条更新,那不知道要等多久才能全部处理完。

先是写一个控制台程序,根据Id分批次,把加密好的数据,以五千条一次写入的频率,一百万数据当成一个批次。

var flag = true;

var begin = 0;
var tmpEnd = begin + 5000;
var end = 1000000;

while (flag)
{
    // 省略读取数据
    foreach (var item in list)
    {
        DataRow dr = dt.NewRow();
        dr["Id"] = item.Id;
        dr["IDCard"] = GetEncryptValue(item.IDCard ?? "");
        dr["PhoneNo"] = GetEncryptValue(item.PhoneNo ?? "");
        dr["IDCardRaw"] = item.IDCard ?? "";
        dr["PhoneNoRaw"] = item.PhoneNo ?? "";
        dt.Rows.Add(dr);
    }

    using (SqlConnection conn = new SqlConnection(connStr))
    {
        conn.Open();
        SqlBulkCopy bulkCopy = new SqlBulkCopy(conn);
        bulkCopy.DestinationTableName = "enc_tmp";
        bulkCopy.BatchSize = dt.Rows.Count;

        bulkCopy.WriteToServer(dt);
    }

    begin = tmpEnd;
    tmpEnd += 5000;

    if (tmpEnd >= end || list == null || !list.Any())
    {
        flag = false;
    }

    Console.WriteLine(begin);
}

为保证写入的速度,先不要在那个临时表建索引,等数据写进去后再给Id建索引。

把数据写进临时表后,下面就是直接用SQL脚本来批量更新了。

-- 建索引
create index idx_enc_tmp_id on enc_tmp (id)


-- 批量更新
update dbo.yourtable
set PhoneNo= a.PhoneNo, IDCard = a.IDCard
from dbo.yourtable b
inner join dbo.enc_tmp a
on a.id=b.id
-- 这里更新要看数据库的配置,如果配置高,可以一次更新,不然就建议25万或50万一个批次
-- where a.id >= 0 and a.id <= 500000


-- 查询校验一下
SELECT top 100 [id]     
      ,[IDCard]     
      ,[PhoneNo]
FROM dbo.yourtable WITH (NOLOCK)
where id > 0 and id <= 500000 
order by id asc

-- 清除临时表的数据
truncate table dbo.enc_tmp

-- 删除索引
drop index idx_enc_tmp_id on enc_tmp

总结

设计系统的时候,数据安全还真的是不容小觑的,对一些敏感信息还是要加密入库的。

修改数据的过程中,也涉及到了两个知识点,数据的批量插入和批量更新。

本文首发于我的个人公众号 不才老黄 ,不定期发布一些内容,有兴趣的可以关注一下哟!

posted @ 2020-08-14 20:14  Catcher8  阅读(666)  评论(0编辑  收藏  举报