数据库热迁移(sqlserver pgsql)

2023年 9月 29日 63.2k 0

数据库热迁移(sqlserver pgsql)

在进行数据迁移前 我们要先清楚如何进行迁移对业务影响最小? 如何性能最高的进行迁移数据库? 迁移过程中会出现哪些问题。

如何进行迁移对业务影响最小

同步方式1

数据迁移的过程中,最简单暴力的方式直接导出数据库中所有的sqlserver语句,编写脚本,将千万数据量转换成pgsql语法,这种方式会产生很多的问题

缺点

  • 数据迁移效率:将千万级别的数据量通过脚本转换和导入可能会非常耗时和耗资源。数据导出时一个漫长的过程,且可能会让线上服务宕机,同时在千万级别数据量同时插入一直占用连接,也会导致数据库宕机,最终导致同步数据丢失 失败。
  • 数据一致性:直接导出和转换数据可能导致数据一致性问题。在数据库迁移过程中,数据可能会发生变化,例如新增、删除或修改。简单地导出和转换数据可能无法捕捉到这些变化,导致目标数据库中的数据不一致。
  • 同步方式2

    编写业务进行同步

    优点

  • 减少数据丢失风险:热同步可以最大程度地减少数据丢失的风险。 可以通过编写日志,具体查看同步到的位置,具体到几百行的位置,同步时如有一条数据同步失败,通过日志记录及时的发现。
  • 高可用性:编写合理的业务,几乎不会对正在运行的业务产生影响 每次只查询一批数据,插入一批数据,不会对数据库造成很大的压力。如果意外宕机的情况下,也能及时找到数据同步的位置,继续进行数据的同步
  • 实时性:业务可以实现实时的数据同步时,能根据sqlserver日志进行 进行同步,当有新的语句插入时,及时检测到日志同步到另一个数据库。
  • 如何性能最高的进行迁移数据库?

    如上所示,我们首先采用第二种同步方式。编写合理的sql语句进行数据的同步,在批量请求数据的时候我们可能会遇到问题就是内存问题,如果数据量请求一旦过多就会导致数据库崩溃,cpu爆满,所以我们编写sql语句时,选择合理的索引。(比如深度分页问题 当你查询的数据靠后时,没有合适的索引就会造成全表扫描,导致数据库宕机)

    当插入语句过多数据量庞大时, 造成B+树的深度过高,需要重复的扫描磁盘。所以再插入语句前为数据表建立合适的索引。

    迁移过程中同步问题

    在sqlserver中,有很种类型的日志,选择适合自己业务场景的日志进行使用,这里我们使用CT日志结合业务进行增量同步。(sql server 中还有cdc日志 记录了详细更改的数据),CT里面记录了原表中修改新增或删除的id 我们集体通过id找到原表中的数据,进行删除或者是修改新增。

    开启CT

    表开启CT

    t_log 表名称

    ALTER TABLE t_log
    ENABLE CHANGE_TRACKING
    

    查看某张表CT追踪

    SELECT * FROM CHANGETABLE(CHANGES t_log, 0) as tbver
    

    查询出来的字段有如下

    //表示更改的版本号。每次更改都会递增版本号。
    SYS_CHANGE_VERSION
    
    //表示创建更改的版本号。对于插入操作,该字段的值等于 SYS_CHANGE_VERSION 的值;
    //对于更新和删除操作,该字段的值表示最初创建更改的版本号
    SYS_CHANGE_CREATION_VERSION
    
    //表示更改的操作类型。可能的值包括 'I'(插入)、'U'(更新)和 'D'(删除)。
    SYS_CHANGE_OPERATION
    
    //表示发生更改的列的位图。每个位表示对应列是否发生了更改。
    //如果对应位为 1,则表示该列发生了更改;如果对应位为 0,则表示该列没有发生更改
    SYS_CHANGE_COLUMNS
    
    //更改的上下文信息。该字段的值通常为空.
    SYS_CHANGE_CONTEXT
    
    //当前表主键
    id
    

    如下编写具体同步业务(数据层涉及内部安全不在此展示)

    package biz.yuanbei.father;

    import biz.yuanbei.dao.sqlserver.SqlSyncVersionDao;
    import biz.yuanbei.framework.common.utils.SyncDataDto;
    import biz.yuanbei.redis.dao.RedisDao;
    import biz.yuanbei.redis.dao.RedisLockDao;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
    import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
    import org.springframework.util.CollectionUtils;

    import javax.annotation.Resource;
    import java.util.List;

    @Slf4j
    public abstract class DataSyncHelper {

    @Autowired
    protected SqlSyncVersionDao sqlSyncVersionDao;

    @Resource
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    protected String KEYVALUE;

    public abstract void setVariable(String value);

    //清除所有的缓存
    public abstract void claneCache();

    protected abstract T fetchById(int Id);

    protected abstract int update(T elem);

    protected abstract int removeById(T ele);

    protected abstract int getCount(SyncDataDto syncData);

    protected abstract List getList(SyncDataDto syncData);

    protected abstract List convertTo(List dataList);

    protected abstract void StopSyncThenSync();

    protected abstract int[] insertBatch(List elems);
    protected abstract int[] insertBatchs(List elems);

    public void syncStart(SyncDataDto syncData, int pageSize) {
    // 获取需要同步的数据总数
    int count = getCount(syncData);
    if (count

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论