我想了很久为什么JDBC API提供了一个自动提交模式(java.sql.Connection.setAutocommit()
)。这似乎是一个诱人的麻烦,只是引诱人们陷入困境。我的理论是,它只添加到JDBC中,以便简化使用JDBC创建编辑和运行SQL的工具的供应商的生活。是否有其他理由打开自动提交,还是总是出错?为什么设置Autocommit为true?
回答
不幸的是,使用自动提交是数据库特定的(就像事务行为一样)。我认为,如果你没有一个全球的,程序化的交易策略,自动提交可能比只希望每个人都能正确地关闭/回滚交易要好。
说到MySQL,您可以在默认情况下保持autocommit = true,并且在您开始事务时它会自动关闭它。设置autocommit = false的唯一原因是,如果您想要在没有BEGIN的情况下尝试启动事务时强制执行错误。
为了简化今天典型的Java + MySQL应用程序,我会或多或少地忽略自动提交设置,使用开放会话视图模式并称其为好。
我强烈劝阻显式RDBMS行锁,并使用乐观锁。 Hibernate为乐观锁定提供了内置支持,但即使对于手写代码,它也是一种简单的模式,并且可以提供更好的性能。
提交模式改变数据库持有锁的方式。
建议仅在事务模式下禁用自动提交模式。这样,您可以避免为多个语句保留数据库锁定,从而增加与其他用户发生冲突的可能性。
...
为了避免交易过程中出现冲突,数据库管理系统使用的锁,机制,阻止他人访问正由事务访问的数据。 (请注意,在自动提交模式,其中每条语句是一个事务,持有锁只有一个声明。)
http://download.oracle.com/javase/tutorial/jdbc/basics/transactions.html
鉴于即使mySQL和DB2最近都是多版本的,该教程也变得有些过时。 :( – Affe 2010-12-15 19:40:26
快照隔离级别不是免费的:http://blogs.msdn.com/b/sqlserverstorageengine/archive/2008/03/30/overhead-of-row-versioning.aspx您可以获得并发快照隔离,但是会增加额外的开销 – hythlodayr 2010-12-15 19:50:47
理解你获得锁的方式始终是相关的 – 2010-12-15 20:01:17
只需要合理的理由,我可以看到的是摆脱connection.commit()
和connection.rollback()
简单的单一查询事务处理小应用程序中的样板。原始形式的JDBC本身就需要很多样板。每一行都使JDBC对于初学者来说不那么可怕。
我正在使用的代码库的95%现在涉及单个更新,其中自动提交是完全合理的。所以,我们默认它。只需将它关闭足够长的时间以完成需要成为事务的代码段,然后自动提交即可重新开始!
请记住,交易可能会导致交易管理器发生交易超时。你在每个查询中设置了超时时间吗? – 2017-12-29 08:33:36
我几乎总是以autocommit = true运行。 99%的时间,我的更新是原子。当然,在某些情况下,如果您编写借方,然后尝试写入您希望回滚的信用额度失败。但根据我的经验,这些比较少见。通常我写的每个记录都是独立的。在这种情况下,在每次写入都很方便之后,不需要费心提交一次提交。它在这里和那里保存了一行代码。如果考虑到程序的结构,这意味着我不需要额外的try/catch块或者我不需要在函数之间传递连接对象,它可以节省更多的时间。它可以节省那些忘记做提交的烦人的错误。
我发现它可以“引诱某人陷入麻烦”的唯一方法是他决定关闭自动提交并进行提交或回滚比较麻烦,因此他更新了应该在事务中单独进行的更新。然后,只要没有任何事情会中止交易,所有事情都可以正常工作。如果测试场景不足,我可以想象这会滑入生产。
但是你几乎可以对任何语言的任何特征说几句话。就像,假设你编写一个程序来处理数字,90%的时间适合长时间,但是现在或许会变得更长。面对这种情况,正确的做法是使用BigInteger或创建一个新类来处理更大的数字。一个懒惰的程序员可能会被诱使用很长的时间,因为它通常会起作用,而其他替代方法则很麻烦。您是否因此得出结论:Java不应该包含long(或int),因为有人可能会在不恰当时引诱它们使用它们?
如果在您的程序中大部分更新必须在事务上下文中完成,请关闭自动提交。它的存在并不会伤害你。当它方便时,它在那里,但当它不是时,你可以关闭它。
由于JDBC 3规范,“自动提交”模式下的连接不能有多个Statement打开。因此,在外部SELECT循环内嵌套的UPDATE甚至SELECT会导致问题。 – 2012-06-05 00:36:01
这不仅是原子性,如果事务管理器支持事务,事务也可以分配超时。使用自动提交和无查询超时可以使您陷入未检测到的SQL性能问题,挂起沉重的查询等。 – 2017-12-29 08:35:28
我已经离开了Javaland多年,所以也许新版本的Java不同或者我只是误解了事情。但是我确信在执行带有自动提交的查询时,我得到了SQL超时。我对在开发环境中发现的查询有很多美好的回忆,但在产品中超时。也许默认值是不同的或者什么的。无论如何,依靠暂停来告诉你,你有一个性能问题是一个非常钝的工具。 – Jay 2017-12-29 16:31:24
自动提交很方便;但随着JDBC 3规范的变化,变得不那么有用。
由于“自动提交”模式下的JDBC 3连接不能打开多个语句。执行另一个语句,将关闭第一个 - 包括任何ResultSet。
因此,在SELECT中循环并发布UPDATE(甚至嵌套的SELECT)将会失败。显然这是一种犯罪,实际上想做些什么与你的外部SELECT的结果!
不管怎么说,依赖于特定的驱动程序版本& ..但在一般的JDBC 3.0规范似乎强制此无益的行为。升级驱动程序也可能无益地“发现”这种行为。
为什么使用自动提交?本来,这很有帮助&方便。至于其他的答案说,JDBC需要丰富金额废话和处理能正确调用.. JDBC是不是一个真正的精心设计的API :(
这些天来,你最好使用Hibernate或Spring的JdbcTemplate。 。如果你正在做servlet/web应用程序,在“用户请求”的边界放置事务管理(开始/结束)或Hibernate会话(绑定到线程本地)。
例如,get在ServletRequest的开始处绑定你的连接/事务;并在最后返回它
你可以使用javax.servlet.Filter或类似的方法,并绑定它到线程局部,使静态帮手得到它或需要它,等
请不要建议绑定到Web请求ANTI模式的连接/交易/会话......如果您希望您的交易跨越例如请求处理,multiplart上传处理,发送正文给客户端连接速度慢,你可以做到这一点,但在几乎所有情况下,我都会说这是非常糟糕的主意。 – 2017-12-29 08:38:12
谢谢@PiotrMüller - 任何推理或参考?我可以预料,对于几乎所有的模式,你都可以想出0.001%的不好的情况,但把“孤立的问题角落案例可能”与“几乎所有案例”区别开来可能会更好 - 当时我给出了这个建议(2012年),我相信这是很好的建议。用户请求边界是HTTP服务应用程序中最基本和重要的边界。因此,这是一个强大而明显的候选设计。任何替代解决方案可能会更复杂。 – 2018-01-08 03:34:50
在Web应用程序中,大多数提到的“不好的情况”将适用(对于任何典型的Web应用程序)。在视图中启用会话,您应确保立即解决很多技术问题,例如,响应缓冲:确保事务和SQL连接在整个客户端连接拉动响应的时间内不是跨度(为什么在客户端具有低带宽的情况下长时间保持SQL连接)。如果应用程序很快就会遇到设计/性能问题增长。对于快速的几个星期小项目,这可能是一些解决方案,但我不会推荐它有任何大的 – 2018-01-26 08:45:10
那么有需要仔细看一下,同时启用“自动提交”在全球层面一定的条件:
a。)查询级别的事务管理将留给用户,对于一个实例,如果需要一堆查询来一起成功或失败,那么它需要在BEGIN下进行包装并提交事务。 )请记住,启用“自动提交”时不会回滚。
c)还有写作(提交)每一笔交易的开销。 d))对于只读查询,没有明确需要“自动提交”,但通过启用“自动提交”,它会自动执行所有查询。
如果表锁定是启用自动提交的唯一考虑因素,那么它可能不是一个好主意,相反可能会采取较低的锁定超时。
- 1. 为什么HasLoadedOrAssignedValue属性设置为true?
- 2. 为什么TRUE ==“TRUE”在R中为TRUE?
- 3. MySQL:START TRANSACTION将'autocommit'设置为关闭?
- 4. 为什么我要在ContentControl上将IsTabStop设置为true?
- 5. 为什么我无法将QUERY_REWRITE_ENABLED设置为TRUE?
- 6. 为什么.CausesValidation按钮默认设置为True?
- 7. 为什么不把ignoreDupResponse默认设置为true在A4J
- 8. 为什么在Save()时不会将IsLoaded设置为true?
- 9. 为什么我得到的错误显然jsonStoreEnabled未设置为true,并且确实将其设置为true?
- 10. 检查值是否设置为true并且为true true
- 11. 不ManualResetEvent的设置为true
- 12. 如何设置OnClientClick为true?
- 13. Selenium为什么为firefox驱动程序设置acceptuntrustedcertificates为true不起作用?
- 14. jboss eap解决方法默认设置连接:autocommit = true
- 15. 为什么不设置clearTaskOnLaunch =“true”会导致OnCreate被调用?
- 16. 为什么我不能使用DataTrigger来设置TextBox.IsEnabled = True?
- 17. 在CrawlSpider的LinkExtractor中设置follow为true的目的是什么?
- 18. 当PictureBox.Visible设置为True时,C#中究竟发生了什么?
- 19. 在StateListDrawable中将android:constantSize设置为'true'有什么好处?
- 20. 为什么设置action_controller.perform_caching = true会中断JavaScript?
- 21. 为什么设置true/false值对React状态不起作用?
- 22. 为什么Boolean.ToString输出“True”而非“true”
- 23. 为什么布尔TRUE不是TRUE?
- 24. 将对象设置为.hidden = true和设置.alpha = 0有什么区别?
- 25. 为什么==返回true?
- 26. 为什么ListBox.Items.IsReadOnly = true? (F#/ Silverlight)
- 27. 为什么要设置ServicePointManager.SecurityProtocol
- 28. 为什么在IsInputKey设置为true时第二次调用PreviewKeyDown事件?
- 29. 当我将DisplayHomeAsUpEnabled设置为true时,为什么我的应用崩溃了?
- 30. 为什么`viewWillAppear`将`animated`设置为true,即使用`present(_,animated:false,_)`呈现?
为了澄清典型的Ja va + MySQL应用程序:将自动提交设置为true。在传入请求(网页或REST/JSON)开始时,打开一个会话(并开始一个事务)一次。如果请求处理正常,请在请求处理结束时提交事务。然后,添加一个回滚到你的500页面的请求渲染。例如,这基本上是Play Framework如何处理事物的。这对用户和开发人员来说很直观。 – 2013-01-11 18:32:09
这是一个很好的答案 - “web请求”应该与web应用程序中的“数据库事务”非常相关。因此我们需要依靠乐观,而不是数据库锁定。它有助于使用OpenSessionInView在整个请求中保持会话打开,包括视图渲染,然后在请求结束时刷新/提交。 – 2013-11-21 09:52:16
在我看来,这不是一个好的答案,如果典型的Java + MySQL应用程序不仅仅是“几个星期的项目”,还可以将会话视为反模式。您会很快失去对应用程序中发生的事情的控制,它几乎可以确定是否会出现性能问题或并发性问题,自动提交将使您无需事务超时或事务超时,如同“一般请求处理超时”一样工作。我会说在90%以上的情况下,web请求NO与SQL事务没有关系 – 2017-12-29 08:30:23