Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么spring/hibernate只读数据库事务的运行速度比读写慢?_Java_Spring_Hibernate_Database Performance_Spring Transactions - Fatal编程技术网

Java 为什么spring/hibernate只读数据库事务的运行速度比读写慢?

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

我一直在研究只读和读写数据库事务的性能。MySQL服务器通过慢速VPN链路远程运行,因此我很容易看到事务类型之间的差异。这就是连接池,我知道它是基于比较第一次和第二次JDBC调用而工作的

当我将Spring AOP配置为在DAO调用中使用只读事务时,调用速度比读写慢30-40%:

<!-- 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进行来回对话。这是对战

  • 有人能解释一下为什么只读电话占用的时间更长吗。这是预期的吗

  • 除了改善网络之外,还有什么我做错了,或者我可以做什么来提高他们的速度?刚刚发现了这篇很棒的文章。还有其他意见吗

  • 多谢

    为什么spring/hibernate只读数据库事务的运行速度比读写慢

    问题#1的简短回答是,hibernate通过
    设置会话.Transaction.read.only
    同步JDBC调用启动
    @事务(readOnly=true)
    会话,并以
    设置会话.Transaction.read.write
    调用结束。执行读写调用时不会发送这些调用,这就是只读调用速度较慢的原因

    好的,这是一次有趣的旅行。我有很多东西要学习和分享。下面的一些应该是显而易见的,但希望我的无知和我所学到的将对其他人有所帮助

    对问题#2的较长回答涉及以下我为尝试改善远程数据库性能而采取的步骤的细节:

  • 我们做的第一件事是在阅读本文后将数据库VPN从TCP切换到UDP。唉。我应该知道这件事的。我还将以下设置添加到OpenVPN客户端和服务器配置中。只读事务开销从480ms下降到141ms,但仍然超过了读写的100ms。大获全胜

    ; Got these from:
    ; https://community.openvpn.net/openvpn/wiki/Gigabit_Networks_Linux
    proto udp
    tun-mtu 6000
    fragment 0
    mssfix 0
    
  • 在仔细观察tcpdump输出(
    tcpdump…-X
    )时,我注意到有很多不必要的自动提交和只读/读写JDBC调用。升级到我们使用的awesome库的更新版本有助于实现这一点。在版本2.4.1中,他们添加了一些智能,从而减少了一些调用。只读事务开销降至120毫秒。读写速度为100ms。很好

  • HikariCP的作者Brett Wooldridge向我指出MySQL驱动程序设置可能会有所帮助。谢谢你,伙计。将以下设置添加到MySQL JDBC URL中会告诉驱动程序使用连接的软件状态,而不是询问服务器状态

    jdbc:mysql://.../database?useLocalSessionState=true&useLocalTransactionState=true
    
    这些设置导致删除更多的同步JDBC命令。只读事务开销降至60毫秒,现在与读写相同。呜呼

    编辑/警告:在发现驱动程序未发送事务信息的错误后,我们实际上回滚了添加
    useLocalTransactionState=true
    。不确定这些bug是在驱动程序、hibernate还是我们的代码中

  • 但在进一步查看tcpdump输出时,我仍然看到正在发送只读/读写事务设置。我的上一个修复方法是编写一个自定义只读检测池,如果它看到对连接的第一个调用是
    connection.setReadOnly(true)
    ,它将从一个特殊池中发出连接

  • 使用此自定义池将只读和读写连接的事务开销降低到20ms。我认为它基本上删除了最后一个JDBC事务开销调用。这是我在主页上写下的所有这些内容的来源。代码相对脆弱,依赖Hibernate进行
    连接。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中肯定遇到了问题,这迫使我们尽快在生产中删除该设置。然而,我没有时间对它进行更多的测试。