2020-11-17 问题记录

问题记录

17日生产问题记录:
1、移动端时间异常bug(暂未确定是前端还是后端问题~)
有使用者反馈,移动端的查询接口出现返回信息错误情况,错误情况是返回的日期应该是2020-11-15 15:30:00,结果返回信息为2046-11-15 15:30:00,查看后端代码,由于前端要求返回的是时间戳,所以后端的SQL查询进行了格式化,如下:
在这里插入图片描述
将此SQL在测试环境的Oracle数据库可以正常查询到结果,且经过时间戳转换工具也是正常时间,生产上一直也是正常的,没有出现过时间戳格式化错误的问题。
解决方案:需要使用者再尝试复现一次,多次切换查询条件,验证问题。

2、开发功能的代码评审意见
(1)代码中使用了几个字符串常量,需要自定义数据字典,避免使用字符串常量。
(2)idea在mvn clean package的时候,指定的settings.xml文件没有生效,需要加-s参数,暂未解决
(3)需要多测试查询Redis服务和原持久层框架切换为jpa后的接口。

3、接口莫名出现503
生产环境上以前一直容易出现504或者是500错误,今天忽然出现503错误,领导让我去排查,在复现过程中,发现接口信息时有时无,且503一般都是网络负载问题,将问题反馈给领导,确定一下是否有在生产环境做压力测试,导致服务器负载出现问题或者是网关是否有问题。
后续反馈:系统间调用采用的服务网格的边车模式,边车相关存在异常,找到相关负责人去排查后解决。
4、生产数据库表恢复
在服务网格问题排查后,对系统进行重启和升级后,发现启动日志中报错,报错信息为表或视图不存在,查看报错SQL,发现是那张最重要的一张表,所以项目组后端成员紧急开会讨论问题所在。
登录生产环境数据库,对该表进行查询后,发现真的删除掉了,而且打电话给运维人员,也得到了确定,是运维人员的误操作导致,所以要尽快恢复。众人拾柴火焰高,开始对数据库表的操作进行分析:
(1)查看Oracle数据库回收站

select object_name,original_name,partition_name,type,ts_name,createtime,droptime from recyclebin;

(2)进行恢复

FLASHBACK TABLE SYS_C008097 TO BEFORE DROP;

在执行第二步操作后,发现表结构已经恢复,但是数据没有恢复,后来运维确定后,是由于使用了truncate 导致数据无法恢复。。

询问原因,是由于近期在做数据库国产化迁移,已将此表的信息迁移到了其他数据库,但是原本想要删除迁移目标库中的此表,由于删除时没有注意,误删了生产上正在使用的表,历史数据也已经迁移到国产化数据库中,所以也还是有历史数据可以恢复的。

恢复方案:
(1)使用迁移工具恢复:由于工具的局限性,仅可以将Oracle数据库迁移至国产化数据库,暂不支持逆向操作。
(2)使用其他数据迁移工具:由于生产环境内网严格,其他工具使用需要提交工单,且需要很多流程,比较复杂。
(3)写个嵌入的程序接口,去迁移目标库查询,再插入回生产数据库表中

经过讨论后,最后采用第三中方式。

数据恢复

恢复方案:
使用最简单的JDBC方式分别连接两个数据库,直接使用main方法的方式实现:

public class DB2DB {
    public static void main(String[] args) {
        DB2DB test = new DB2DB();
        try {
            test.deal();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    private Connection getPolarconn(){
        try {
            Class.forName("com.aliyun.polardb.Driver");
            return DriverManager.getConnection("jdbc:polardb://XXX.XXX.XXX.XXX:XXXX/DB","user","password");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    private Connection getOracleconn(){
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            return DriverManager.getConnection("jdbc:oracle:thin@//XXX.XXX.XXX.XXX:XXXX/DB","user","password");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void deal() throws SQLException {
        //有数据的数据库
        Connection polarConn = getPolarconn();
        Statement itestmt =polarConn.createStatement();
        ResultSet iters = itestmt.executeQuery("select * from test_table_1");

        //结果集获取到的长度
        int size = iters.getMetaData().getColumnCount();
        //直接拼接insert into 语句,为第二个数据库做准备 
        StringBuffer sbf =new StringBuffer();
        sbf.append("insert into test_table_1values (");
        String link ="";
        for (int i = 0; i <size ; i++) {
            sbf.append(link).append("?");
            link=",";
        }
        sbf.append(")");
        //目标数据库
        Connection oracleConn = getOracleconn();
        PreparedStatement dataPstmt = oracleConn.prepareStatement(sbf.toString());

        //取出结果集并使用批处理向数据库插入数据
        //完成条数
        int count =0;
        int num=0;
        //取消事务(不写入日志)
        oracleConn.setAutoCommit(false);
        long start = System.currentTimeMillis();
        while (iters.next()) {
            ++count;
            for (int i=1;i<= size;i++) {
                dataPstmt.setObject(i, iters.getObject(i));
            }

            //将预先语句存储起来,这里还没有向数据库插入
            dataPstmt.addBatch();
            //当count 到达 20000条时 向数据库提交
            if (count % 20000 ==0 ){
                ++num;
                dataPstmt.executeBatch();
                System.out.println("第"+num+"次提交,耗时:"+(System.currentTimeMillis()-start)/1000.0+"s");
            }
        }
        //防止有数据未提交
        dataPstmt.executeBatch();
        //提交
        oracleConn.commit();
        System.out.println("完成 "+count+" 条数据,耗时:"+(System.currentTimeMillis()-start)/1000.0+"s");
        //恢复事务
       // oracleConn.setAutoCommit(true);

        //关闭资源
        close(oracleConn,dataPstmt,null);
        close(polarConn,itestmt,iters);

    }

    public  void  close(Connection conn,Statement stmt,ResultSet rs){

        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

使用此方法,在测试环境上尝试,发现80万条数据大约90s左右,考虑后续优化~
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值