休眠自动提交命令强制MySQL在过多的磁盘I / O中运行

亲爱的大家,

我敢肯定,你们中的许多人都在使用Hibernate和MySQL,我自己在这里和那里都使用它。 通常,编程模型是不错的,但是普通的JDBC可以快很多已经不是什么秘密了。 在这篇文章中,我想引起您的注意Hibernate在您的MySQL服务器中引起的一个小问题。

如果跟踪Hibernate发送到MySQL数据库的SQL,就会发现一致地,Hibernate以“ SET autocommit = 0”开始每个事务,并以“ commit”结束,然后是“ SET autocommit = 1”。 这些语句看似无害,但它们使MySQL将某些内部状态刷新到磁盘上。 简而言之,每次Hibernate调用这两个语句之一时,MySQL都会编写通常不会编写的内容。 因此,与使用普通JDBC相比,使用Hibernate会使MySQL服务器在磁盘上的依赖更多。

我做了一个小实验来证明这一点。 要重复此实验,请找到带有MySQL数据库的空闲计算机。 机器不应运行任何会导致磁盘I / O的东西,否则效果将不像我看到的那么容易。

首先,我发送了一整串“ SELECT DUAL DUAL;” 命令进入MySQL提示。 像这样:

while true; do
        echo "SELECT 1 FROM DUAL;"
done | mysql

查看iostat(8)的输出,结果表明机器上没有I / O。 top(1)确实表明机器正在运行。 由此可见,这些SELECT语句不会引起磁盘I / O。

接下来,我添加了Hibernate的自动提交命令,如下所示。

while true; do
        echo "SET AUTOCOMMIT=0;"
        echo "SELECT 1 FROM DUAL;"
        echo "COMMIT;"
        echo "SET AUTOCOMMIT=1;"
done | mysql

这次,iostat(8)确实表明存在磁盘I / O。 MySQL服务器比以前更努力地工作,同时仍然提供完全相同的答案。 这仅来自单个线程。 您的应用程序可能会在多个线程和连接上同时发出这些语句,从而加剧了问题。

对于无论如何都会导致I / O的查询,我认为这种开销可以忽略不计。 对于小型读取查询,这意味着您突然在数据库服务器上执行磁盘I / O。

我还没有找到一种方法来向Hibernate解释我不想让它将自动提交语句发送到数据库。 您可以在Hibernate中关闭自动提交功能,但是只能关闭Hibernate的内部自动提交功能。 它不会停止将这些命令发送到数据库。

读取Hibernate源代码(尤其是org.hibernate.transaction.JDBCTransaction的源代码)可以看到,休眠使它在每次事务之前强制自动提交连接失败,并在之后重置它。 这是硬编码的。 休眠*想要*自动提交为关闭。

如果我的MySQL服务器仅服务于启用了Hibernate的应用程序,我可能会考虑将数据库服务器的默认自动提交模式关闭。 另外,我可以使用elideSetAutoCommits标志,这可能会减少自动提交切换的数量。 但是,这严重破坏了POLA 。 另外,我的服务器不仅仅提供支持Hibernate的应用程序,因此更改默认设置肯定会破坏其他地方。

所以,这让我陷入困境。 我不能告诉Hibernate不要发出“ SET autocommit”,JDBC驱动程序不会禁止它们,也不能告诉MySQL忽略它们。

参考: Hibernate发送自动提交命令会强制MySQLJava Monitor论坛上从我们的JCG合作伙伴 Kees Jan 做过多的磁盘I / O。

快乐编码
拜伦

相关文章:

翻译自: https://www.javacodegeeks.com/2011/07/hibernate-autocommit-commands-force.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值