上期文章分享了数据库归档策略,下面来分享一下生产库删除策略。
需求:
1.三张有关但是不存在外键的表:
rxinfo:存储订单信息;
rxExtendsInfo:存储订单扩展信息;
rxSku:存储订单订单购买的商品信息。
2.三张表均有订单号字段rxId(有索引)
3.删除已归档的数据
策略:
1.从生产库按照rxId正序拿到若干条数据作为预删除数据。
2.一次从归档库遍历当前数据是否已经归档(需要根据订单号遍历3个表)。
3.每遍历一个表,如果不构成删除条件(例如某一订单有字段生产库和归档库不对应),则从预删除订单列表剔除。
4.事务性删除三个表的订单。
优点:充分利用索引,事务性删除3个表数据,保证数据一致性
//每次顺序取批量执行500条
List<Long> rxIdList = rxReadDao.getRxIdPage(500);
logger.info("the rxids ready to delete:{}", rxIdList.size());
if (rxIdList == null || rxIdList.size() == 0) {
break;
}
//记录一下初始的订单列表
List<Long> oriRxIdList = rxIdList;
logger.info("the end date:{}", DateUtil.formatDate(maxDate, "yyyy-MM-dd HH:mm:ss"));
//过滤出可以删除的rxInfo的订单列表
rxIdList = filterRxInfoCanDelList(rxIdList);
//过滤出可以删除的rxExtendsInfo的订单列表
rxIdList = filterRxExtendsInfoCanDelList(rxIdList);
//过滤出可以删除的rxSku的订单列表
rxIdList = filterRxSkuCanDelList(rxIdList);
//事务性删除rx_info中指定订单
if (rxIdList != null && rxIdList.size() > 0) {
orderManager.delRxOrderByRxId(rxIdList);
}
}
private List<Long> filterRxInfoCanDelList(List<Long> rxIdList) {
List<Long> result = new ArrayList<>();
List<RxInfo> rxInfos = rxReadDao.getRxInfoListByRxIds(rxIdList);
List<RxInfo> rxInfosArchive = dataArchiveDao.getRxInfoListByRxIds(rxIdList);
Iterator<RxInfo> it = rxInfosArchive.iterator();
for (RxInfo rxInfo : rxInfos) {
while (it.hasNext()) {
RxInfo in = it.next();
//如果两个实体字段全部相同,代表整个订单可以上出
if (Compare2ObjsUtil.compare(in, rxInfo)) {
result.add(in.getRxId());
it.remove();
break;
}
}
}
return result;
}
private List<Long> filterRxExtendsInfoCanDelList(List<Long> rxIdList) {
List<Long> result = new ArrayList<>();
List<RxExtendsInfo> rxExtendsInfos = rxExtendsInfoReadDao.getRxExtendsInfoListByRxIds(rxIdList);
List<RxExtendsInfo> rxExtendsInfosArchive = dataArchiveDao.getRxExtendsInfoListByRxIds(rxIdList);
Iterator<RxExtendsInfo> it = rxExtendsInfosArchive.iterator();
for (RxExtendsInfo extendsInfo : rxExtendsInfos) {
while (it.hasNext()) {
RxExtendsInfo in = it.next();
//如果两个实体字段全部相同,代表整个订单可以上出
if (Compare2ObjsUtil.compare(in, extendsInfo)) {
result.add(in.getRxId());
it.remove();
break;
}
}
}
return result;
}
private List<Long> filterRxSkuCanDelList(List<Long> rxIdList) {
List<Long> result = new ArrayList<>();
List<RxSku> rxSkus = rxSkuReadDao.getRxSkuListByRxIds(rxIdList);
List<RxSku> rxSkusArchive = dataArchiveDao.getRxSkuListByRxIds(rxIdList);
Iterator<RxSku> it = rxSkusArchive.iterator();
for (RxSku sku : rxSkus) {
while (it.hasNext()) {
RxSku in = it.next();
//如果两个实体字段全部相同,代表整个订单可以上出
if (Compare2ObjsUtil.compare(in, sku)) {
result.add(in.getRxId());
it.remove();
break;
}
}
}
return result;
}
/**
* 根据订单号批量删除订单,保证事务性
*
* @param rxIds
*/
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void delRxOrderByRxId(List<Long> rxIds) {
//批量删除rxInfo 表中指定订单,数据归档专用
rxInfoDao.delRxOrderByRxId(rxIds);
//批量删除rx_extends表中的订单,数据归档专用
rxExtendsInfoDao.delRxOrderByRxId(rxIds);
//批量删除rxSku表中的订单,数据归档专用
rxSkuDao.delRxOrderByRxId(rxIds);
}
取单号的sql
<select id="getRxIdPage" resultType="long">
SELECT
rx_id
FROM
rx_info
WHERE 1=1
<![CDATA[AND created < #{endDate} ]]>
order by rx_id
limit #{pageSize}
</select>
删表的sql
<delete id="delRxOrderByRxId">
delete from rx_info where rx_id in
<foreach collection="rxIds" item="rxId" separator="," open="(" close=")">
#{rxId}
</foreach>
</delete>