gpt4 book ai didi

java - 为什么spring/hibernate只读数据库事务运行比读写慢?

转载 作者:IT老高 更新时间:2023-10-28 13:46:05 24 4
gpt4 key购买 nike

我一直在围绕只读与读写数据库事务的性能进行一些研究。 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 进行更多的来回对话。这是read-only dumpread-write 相比.

  1. 谁能解释一下为什么只读调用需要更长的时间?这是预期的吗?

  2. 除了改善网络之外,我是否做错了什么或者我可以做些什么来提高他们的速度?刚刚发现这篇很棒的帖子有一些 good performance recommendations .还有其他意见吗?

非常感谢。

最佳答案

Why do spring/hibernate read-only database transactions run slower than read-write?

对问题 #1 的简短回答是 hibernate 使用 set session.transaction.read.only 启动 @Transaction(readOnly = true) session > 同步 JDBC 调用并以 set session.transaction.read.write 调用结束。在进行读写调用时不会发送这些调用,这就是只读调用较慢的原因。请参阅下面的我的补救措施。

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

问题 #2 的较长答案涉及我为尝试提高远程数据库性能而采取的以下步骤的详细信息:

  1. 读完这篇 OpenVPN optimization page 之后,我们做的第一件事就是将我们的数据库 VPN 从 TCP 切换到 UDP。 .叹。我应该知道这件事。我还在 OpenVPN 客户端和服务器配置中添加了以下设置。只读事务开销从 480 毫秒降至 141 毫秒,但仍超过读写的 100 毫秒。大获全胜。

    ; Got these from:
    ; https://community.openvpn.net/openvpn/wiki/Gigabit_Networks_Linux
    proto udp
    tun-mtu 6000
    fragment 0
    mssfix 0
  2. 在仔细查看 tcpdump 输出(tcpdump ... -X 为胜利),我注意到有很多不必要的自动提交和只读/读取-write 正在进行的 JDBC 调用。升级到新版本的真棒HikariCP connection pool我们使用的图书馆对此有所帮助。在 2.4.1 版本中,他们添加了一些智能来减少其中一些调用。只读事务开销低至 120 毫秒。读写仍为 100ms。不错。

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

    jdbc:mysql://.../database?useLocalSessionState=true&useLocalTransactionState=true

    这些设置导致更多的同步 JDBC 命令被删除。只读事务开销降至 60 毫秒,现在与读写相同。呜呼。

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

  4. 但在查看更多 tcpdump 输出时,我仍然看到正在发送只读/读写事务设置。我的最后一个修复是编写一个自定义的只读检测池,如果它看到对连接的第一次调用是 connection.setReadOnly(true),它会从特殊池发出连接。

使用此自定义池将只读和读写连接的事务开销降低到 20 毫秒。我认为它基本上消除了最后一个 JDBC 事务开销调用。这里是 two classes that I wrote 的来源从我的主页上写下这一切。代码相对脆弱,首先要依赖 Hibernate 执行 connection.setReadOnly(true) 但它似乎运行良好,我在 XML 和代码中仔细记录了它。

所以在几天的工作中,基本的 @Transaction 开销从 480 毫秒变为 20 毫秒。对 dao.find(...) 方法的 100 次“现实生活” hibernate 调用从 55 秒开始,到 4.5 秒结束。相当踢屁股。希望将速度提高 10 倍总是这么容易。

希望我的经验对其他人有所帮助。

关于java - 为什么spring/hibernate只读数据库事务运行比读写慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34797480/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com