一、前言
需求背景:mysql数据库中有一个表的数据(600多万)有一个字段的内容需要解密再通过另外一种加密方式进行加密再回存。通过java程序计算完成更新。
二、方案一
一条条计算更新。这里是将手机号解密,在通过另外一种方式回存。
算法步骤:
1、查询需要解密的数据总条数
2、循环查询1条数据,进行解密,加密,更新,commit。
public void updateOne() {
int n = 0;
n = getCount();
log.info("待密数据条数:" + n);
if (n > 0) {
for (int i = 0; i < n; i++) {
TmpMUser tmpMUser = getOne();
if (null != tmpMUser) {
String yphone = tmpMUser.getCellphoneSha();
log.info("原手机号:" + yphone);
if (!StringUtils.isEmpty(yphone)) {
yphone = yphone.replaceFirst("86-s4:", "");
String phone = SM4Util.sm4Decode(yphone, keyString);
String origPhone = SHAUtils.getSHA("86-" + phone);
log.info("解密出手机号:" + phone);
tmpMUser.setPhone(phone);
tmpMUserMapper.updateTmpMUser(tmpMUser.getRowId(), phone, origPhone);
tmpMUserMapper.commit();
}
}
log.info("已解密数据条数:" + i);
}
} else {
log.info("没有需要解密的数据");
}
}
存在的问题。
数据量太大,几秒钟才能操作完成一条。原因:每更新一条就commit,消耗数据库性能,第二,更新的条件没有索引,查找数据较慢。
三、方案二
改进,建索引,每200条commit一次。
/**
* 更新200条
*
*/
public void update200() {
int n = 0;
n = getCount();
log.info("待密数据条数:" + n);
if (n > 0) {
for (int i = 0; i < n / 200 + 200; i++) {
List<TmpMUser> tmpMUserList = get200();
if (CollectionUtils.isNotEmpty(tmpMUserList)) {
for (TmpMUser tmpMUser : tmpMUserList) {
String yphone = tmpMUser.getCellphoneSha();
log.info("原手机号:" + yphone);
if (!StringUtils.isEmpty(yphone)) {
yphone = yphone.replaceFirst("86-s4:", "");
String phone = SM4Util.sm4Decode(yphone, keyString);
String origPhone = SHAUtils.getSHA("86-" + phone);
log.info("解密出手机号:" + phone);
tmpMUser.setPhone(phone);
tmpMUserMapper.updateTmpMUser(tmpMUser.getRowId(), phone, origPhone);
}
}
tmpMUserMapper.commit();
}
log.info("已解密数据条数:" + 2 * i + "00");
}
} else {
log.info("没有需要解密的数据");
}
}
四、主要问题
这里更新数据一定需要手动commit,如果没有commit更新是不生效的,所以优化这一步是关键。
优化完成,提升到每秒200条。
/**
* 提交事务
*/
@Update("<script>" +
"commit " +
"</script>")
public void commit();