Kettle——this connection is closed
背景
工作中使用Kettle将源库的数据写入到我的数据库(目标库),步骤是:
执行SQL语句——表输入——表输出
其中 执行SQL语句 和 表输出 都是用的目标库的连接参数,表输入 是源库,发现当源库的数据读取时间超过30分钟,数据流到达 表输出 控件时,报错 this connection is closed.
目前目标库的参数如下:
1、session_timeout = 30分钟;
2、idle_in_transaction_timeout = 300秒
3、statement_timeout = 1小时
4、tcp_user_timeout = 0 毫秒
由于公司对于数据库的底层配置严格控制,不允许随意更改,没办法,只能想其他办法了。
解决方法
方法一
先将源库数据写到文本文件中,然后再从文本文件写入到表
这个办法最直接,但如果源库读取的数据量过大时,需要注意磁盘空间的大小。
但无法保证所有转换的读数时间都可以在30分钟内获得,所以仍然会有转换报错,导致数据更新失败
方法二
虽然和Kettle打交道已经好几年了,但是对于转换中的控件的执行时间还不是特别清楚,只是大概知道转换中的控件是并行的,作业之间是串行的。于是有了以下尝试:
1、目标库使用连接池(失败)
原本没有使用连接池,百度说使用连接池,增加心跳包,保持连接的活跃,试了,失败
2、临时修改会话时长(失败)
执行SQL语句和表输出用的是同一个数据库连接参数,可能共用同一个会话,由于表输出无法执行SQL,便在执行SQL语句中,加入 set session_time to 3600; 失败
3、将执行SQL语句和表输出分成2个转换(失败)
如果执行SQL语句和表输出共用同一个数据库会话,执行SQL语句时,创建了会话,导致表输出的会话也连接,表输出原本可能是懒连接,现在被迫早早建立会话。于是将执行SQL语句和表输入、表输出分为2个转换,失败
这个尝试说明,转换中的所有数据库会话都是单独的。
4、修改目标库连接串(失败)
与使用连接池类似,就是在连接串中加参数保活,失败
5、使用延迟行保持会话连接(偶发成功)
在转换中加入一条数据流处理线,表输入——延迟行——表输出,延迟行设置为20分钟,保证表输入读取数据时,中途有数据流入表输出。
太悲伤了,但以上的尝试也说明了Kettle转换中的控件是根据输入输出流来并行执行的,也就是说,执行一个转换时,所有控件都开始了工作,执行SQL语句开始了执行SQL,表输入开始了读取数据,表输出开始了输出数据,每个控件并行地处理经过自己的数据流,直到所有控件都没有数据流入或流出,整个转换就结束了。
我的处理流程中,执行SQL语句用于删除目标库的数据,表输入读取源库的数据,表输出将数据写入目标库。转换开始后,表输出就创建了数据库会话,等待数据流流入。由于数据流流入的时间超过了session_timeout,目标库关闭了这个空闲会话,所以数据流到达表输出时,报错 this connection is closed.
6、表输出中更改当前会话时长(成功)
一直没有发现表输出执行SQL语句的地方,所以前面更改会话时长的语句放在了执行SQL语句中,后来使用连接池时,发现数据库连接——高级,可以输入SQL语句, set session_time to 3600;

