Java 为什么spring/hibernate只读数据库事务的运行速度比读写慢?
我一直在研究只读和读写数据库事务的性能。MySQL服务器通过慢速VPN链路远程运行,因此我很容易看到事务类型之间的差异。这就是连接池,我知道它是基于比较第一次和第二次JDBC调用而工作的 当我将Spring AOP配置为在DAO调用中使用只读事务时,调用速度比读写慢30-40%:Java 为什么spring/hibernate只读数据库事务的运行速度比读写慢?,java,spring,hibernate,database-performance,spring-transactions,Java,Spring,Hibernate,Database Performance,Spring Transactions,我一直在研究只读和读写数据库事务的性能。MySQL服务器通过慢速VPN链路远程运行,因此我很容易看到事务类型之间的差异。这就是连接池,我知道它是基于比较第一次和第二次JDBC调用而工作的 当我将Spring AOP配置为在DAO调用中使用只读事务时,调用速度比读写慢30-40%: <!-- slower --> <tx:method name="find*" read-only="true" propagation="REQUIRED" /> ... // slower
<!-- slower -->
<tx:method name="find*" read-only="true" propagation="REQUIRED" />
...
// slower
@Transaction(readOnly = true)
...
//慢的
@事务(只读=真)
与:
<!-- faster -->
<tx:method name="find*" read-only="false" propagation="REQUIRED" />
...
// faster
@Transaction
...
//更快
@交易
看看tcpdump,似乎只读事务在与MySQL进行来回对话。这是对战
设置会话.Transaction.read.only
同步JDBC调用启动@事务(readOnly=true)
会话,并以设置会话.Transaction.read.write
调用结束。执行读写调用时不会发送这些调用,这就是只读调用速度较慢的原因
好的,这是一次有趣的旅行。我有很多东西要学习和分享。下面的一些应该是显而易见的,但希望我的无知和我所学到的将对其他人有所帮助
对问题#2的较长回答涉及以下我为尝试改善远程数据库性能而采取的步骤的细节:
; Got these from:
; https://community.openvpn.net/openvpn/wiki/Gigabit_Networks_Linux
proto udp
tun-mtu 6000
fragment 0
mssfix 0
tcpdump…-X
)时,我注意到有很多不必要的自动提交和只读/读写JDBC调用。升级到我们使用的awesome库的更新版本有助于实现这一点。在版本2.4.1中,他们添加了一些智能,从而减少了一些调用。只读事务开销降至120毫秒。读写速度为100ms。很好
jdbc:mysql://.../database?useLocalSessionState=true&useLocalTransactionState=true
这些设置导致删除更多的同步JDBC命令。只读事务开销降至60毫秒,现在与读写相同。呜呼
编辑/警告:在发现驱动程序未发送事务信息的错误后,我们实际上回滚了添加useLocalTransactionState=true
。不确定这些bug是在驱动程序、hibernate还是我们的代码中
connection.setReadOnly(true)
,它将从一个特殊池中发出连接
连接。setReadOnly(true)
第一件事,但它似乎运行良好,我在XML和代码中仔细记录了它
因此,在几天的工作中,基本的@Transaction
开销从480ms增加到20ms。100个对dao.find(…)
方法的“真实”hibernate调用从55秒开始,到4.5秒结束。真是太棒了。希望速度提升10倍总是这么容易
希望我的经验能帮助其他人。这真的很奇怪。顺便说一句,有趣的阅读@Leo,谢谢。干得好。您还可以研究MySQL驱动程序属性
alwaysSendSetIsolation
和readOnlyPropagatesToServer
。一个或两个都可以消除对特殊池包装器的需要。要进一步提高性能,您可能需要调查cacheResultSetMetadata
、cacheServerConfiguration
和tcpRcvBuf
。谢谢@brettw。我已经看过了readOnlyPropagatesToServer
,我认为它不会有什么帮助。问题在于hibernate总是设置然后重置连接上的只读状态。我不认为司机可以无视他们盲目,但我的代码有这种奢侈。我会查其他的。我想你会找到的。旧文章,但基本上不使用事务性注释进行只读操作,或者另外使用propagation=propagation.SUPPORTS
。我很好奇这会如何影响Hibernate级别的setReadOnly()/setAutoCommit()行为。是的,我需要在@DelGurth进行更多测试。我们在5.1.40中肯定遇到了问题,这迫使我们尽快在生产中删除该设置。然而,我没有时间对它进行更多的测试。