我每 2 小时在我的服务器上使用 cron 每天运行一次 ETL 进程。ETL 进程填充运行 Greenplum 的报告数据库。我注意到 ETL 进程通常会停滞,而“事务中的空闲”通常是导致进程停滞的原因。对于这些类型的进程,我该如何调查它源自哪种服务?我猜是这样的,但我不太确定,因为当我运行“sudo /etc/init.d/apache2 graceful”时,它通常会清除空闲事务。
我正在使用 Sun Java 在 Ubuntu 服务器上运行 ETL 流程。希望能有一些调试技术或解决方案来改进该流程。
答案1
“事务中空闲”意味着在数据库连接上启动了一个事务但尚未完成,并且不再有任何查询在运行。
在数据库服务器的进程列表中(例如:)ps -ef | grep "idle in"
,您将找到处于该状态的连接。它将显示类似以下内容:
postgres 15268 12917 0 22:36 ? 00:00:03 postgres: user user x.x.x.x(59830) idle in transaction
这(59830)
是机器上的端口x.x.x.x
。
然后,您可以在x.x.x.x
机器上运行以下命令来查找哪个进程建立了该数据库连接:
netstat -np | grep 59830
这会给你类似这样的结果:
tcp6 0 0 x.x.x.x:59830 dbserver:5432 ESTABLISHED 25254/java
(或 Apache,或任何进程)。在此示例中,25254
是进程的 PID。
这回答了你帖子正文中的问题。
当然,处理起来是一个更复杂的问题。为什么这个连接启动了事务却没有完成 = 编码错误。解决方案:正确编码。
笔记:
Pentaho PDI 有一个坏习惯,就是长时间让事务处于闲置状态。假设您在 PDI 中有一个步骤更新了一些行。它如下:
input step --> filter step --> update step
假设您在 上将提交批次设置为 100。update step
您说,更新步骤中有 75 行,并且input step
仍在提取行和filter step
筛选行,但由于条件,update step
暂时不会将任何内容转移到 ,因为 中没有符合条件的行filter step
。那么您有什么?数据库连接idle in transaction
(75 行已更新但未提交)。
所以这一切都很好,只是对于收到有关该长期运行事务的警报的 DBA 来说有点烦人。
但是现在,假设您有另一个步骤,它分支出来filter step
并以不同的方式更新同一张表,并且不知何故,一条记录是 75 条更新行的一部分(但尚未提交),update step 2
现在需要更新此行。会发生什么?停滞。在提交批处理update step 2
之前无法更新行。update step
并不是说这就是您所遇到的情况,因为您似乎已经发现但尚未确认您的阻塞事务是在 Apache 而不是 PDI 下运行的。但以上是对可能发生的问题的描述,以说明通常发生的情况。