您的位置:首页 > 编程语言 > Java开发

crontab java -jar --------- java.sql.SQLRecoverableException: 无法从套接字读取更多的数据

2018-01-18 10:21 489 查看
前阵子自己尝试用maven和mybatis写了一个小程序,本来是对业务系统的定时任务做监控的。

如果定时任务正常,就继续监控;如果定时任务没有正常写库,就发一个短信给我。

多么简单的需求,就是一个简单的读库操作。crontab里面定时执行一个java -jar,直接执行jar包,jar包代码直接读库,正常则继续;不正常则发短信。

结果倒好,隔三差五的误报警,简直被玩死。瞅来瞅去自己都快对报警短信麻木了。



准备分析这个问题的,结果去看crontab的系统日志,发现自己账户没有权限。但是crontab的定时监控脚本是自己写好保存并启动的。然后分析下来,觉得是因为直接-jar执行,没有跑在容器里面(如果是tomcat执行的话,就相当于跑在tomcat容器里面。log在tomcat里面可以看到)

自己改了一下代码,将原来代码里面的e.printStackTrace();改成了



这样至少可以把crontab的应用层面的log保留下来并自己查看了。观察了几天,发现报错都是下面这一种问题



在网上查了一些帖子,有人说是因为mybatis超时导致的,于是在config.xml中新增了

    <settings>

        <setting name="defaultStatementTimeout" value="720"/>

    </settings>

参数设置,然后发现没有效果。

又有人讲是需要在DataSource段中新增

                <property name="poolPingQuery" value="SELECT SYSDATE FROM dual" />

                <property name="poolPingEnabled" value="true" />

经人指点,应该在DB操作前后打印准确的时间戳,通过时间方便查找问题。于是进行了打印,果然可以看到问题

按照网上的样例,自己写了一个Mybatis读取数据库的代码。如下:

try {

                inputStream = Resources.getResourceAsStream(resource);

                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

                sqlSession = sqlSessionFactory.openSession();

                Map<String, Object> param = new HashMap<String, Object>();

                param.put("codeA", jobName);

                param.put("codeD", date);

                System.out.println("Before DB access " + String.valueOf(new SimpleDateFormat("yyyyMMdd HH:mm:ss:SSS").format(new Date())));

                tab = sqlSession.selectOne("com.lcd.cf.dao.ConsumeJournalDetailTabMapper.queryReturnCodeOfBatch",

                        param);

                System.out.println("After DB access " + String.valueOf(new SimpleDateFormat("yyyyMMdd HH:mm:ss:SSS").format(new Date())));

            } catch (Exception e) {

                System.out.println("After DB access " + String.valueOf(new SimpleDateFormat("yyyyMMdd HH:mm:ss:SSS").format(new Date())));

                System.out.println(e.toString());

            } finally {

                if (sqlSession != null) {

                    sqlSession.close();

                }

                if (inputStream != null) {

                    try {

                        inputStream.close();

                    } catch (IOException e) {

                        System.out.println(e.toString());

                    }

                }

            }

测试下来功能实现了,但是实际跑这段代码发现问题如下:

生产上会连续多次读取多条数据,就是多次调用上面这段逻辑。

观察后台log发现:

20180201 19:30:01:704

Before DB access 20180201 19:30:02:036

Input args: {codeA=放款通知, codeD=20180201}

After DB access 20180201 19:30:58:065

Before DB access 20180201 19:30:58:116

Input args: {codeA=还款提醒1, codeD=20180201}

After DB access 20180201 19:30:58:146

Before DB access 20180201 19:30:58:181

Input args: {codeA=还款提醒2, codeD=20180201}

After DB access 20180201 19:30:58:221

Before DB access 20180201 19:30:58:265

Input args: {codeA=还款提醒3, codeD=20180201}

After DB access 20180201 19:30:58:292

Before DB access 20180201 19:30:58:325

Input args: {codeA=还款提醒4, codeD=20180201}

After DB access 20180201 19:30:58:361

Before DB access 20180201 19:30:58:399

Input args: {codeA=逾期提醒, codeD=20180201}

After DB access 20180201 19:30:58:446

Before DB access 20180201 19:30:58:479

Input args: {codeA=逾期提醒2, codeD=20180201}

After DB access 20180201 19:30:58:563

看时间打印,第一次读取,花了56s,而后面的每次读取都是不到1s就可以搞定。

为什么第一次会这么慢,后面快起来又是为啥?都是同样的逻辑。每次读取数据库都会关闭session的。后续的读库操作,不应该和前面的操作一样的开销吗?

最省事的解决方案是把读取数据库的超时报错调整一下。过两天看效果
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mybatis java Oracle