Hibernate自动提交命令强制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; doecho "SELECT 1 FROM DUAL;" done | mysql查看iostat(8)的輸出,結果表明機器上沒有I / O。 top(1)確實表明機器正在運行。 由此可見,這些SELECT語句不會引起磁盤I / O。
接下來,我添加了Hibernate的自動提交命令,如下所示。
while true; doecho "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的源代碼)可以看到,Hibernate使它在每次事務處理之前強制自動提交連接為假,并在之后進行重置。 這是硬編碼的。 Hibernate*想要*自動提交關閉。
如果我MySQL服務器僅服務于啟用了Hibernate的應用程序,我可能會考慮將數據庫服務器的默認自動提交模式關閉。 另外,我可以使用elideSetAutoCommits標志,這可能會減少自動提交切換的數量。 但是,這嚴重破壞了POLA 。 另外,我的服務器不僅僅支持啟用了Hibernate的應用程序,因此更改默認設置肯定會破壞其他地方。
所以,這讓我陷入困境。 我不能告訴Hibernate不發出“ SET autocommit”,JDBC驅動程序不會禁止它們,也不能告訴MySQL忽略它們。
參考: Hibernate發送自動提交命令會強制MySQL在Java Monitor論壇上從我們的JCG合作伙伴 Kees Jan 做過多的磁盤I / O。
快樂編碼 拜倫相關文章:
- Hibernate映射集合性能問題
- DataNucleus 3.0與Hibernate 3.5
- 提升您的Hibernate引擎
- GWT 2 Spring 3 JPA 2 Hibernate 3.5教程
- JBoss 4.2.x Spring 3 JPA Hibernate教程
翻譯自: https://www.javacodegeeks.com/2011/07/hibernate-autocommit-commands-force.html
總結
以上是生活随笔為你收集整理的Hibernate自动提交命令强制MySQL在过多的磁盘I / O中运行的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么检验路由器好坏如何一检测路由器
- 下一篇: 从数百万个光纤(而不是数千个线程)中查询