Java 为什么将 Autocommit 设置为 true?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4453782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why set Autocommit to true?
提问by Nathan Hughes
I have wondered for a long time why the JDBC API provides an autocommit mode (java.sql.Connection.setAutocommit()
). It seems like an attractive nuisance that just lures people into trouble. My theory is it was only added to JDBC in order to simplify life for vendors who wanted to create tools for editing and running SQL using JDBC. Is there any other reason to turn on autocommit, or is it always a mistake?
我一直想知道为什么 JDBC API 提供自动提交模式 ( java.sql.Connection.setAutocommit()
)。这似乎是一种诱人的麻烦,只会引诱人们陷入困境。我的理论是,它被添加到 JDBC 中只是为了简化想要使用 JDBC 创建用于编辑和运行 SQL 的工具的供应商的生活。是否有任何其他原因打开自动提交,或者它总是一个错误?
采纳答案by Will Iverson
Unfortunately, using autocommit is database specific (as is transaction behavior). I think if you don't have a global, programmatic transaction strategy, autocommit is probably better than just hoping everyone properly closes/rolls back transactions.
不幸的是,使用自动提交是特定于数据库的(事务行为也是如此)。我认为如果你没有全局的、程序化的事务策略,自动提交可能比只是希望每个人都正确关闭/回滚事务更好。
Speaking for MySQL, you can leave autocommit=true on by default, and it will automatically turn that off when you BEGIN a transaction. The only reason to set autocommit=false is if you want to force an error if someone tries to start a transaction without a BEGIN.
说到 MySQL,你可以默认启用 autocommit=true,当你开始一个事务时它会自动关闭它。设置 autocommit=false 的唯一原因是,如果有人试图在没有 BEGIN 的情况下启动事务,您想强制出错。
For simplicity in a typical Java + MySQL application today, I would more or less ignore the auto-commit setting, use an open-session-in-view pattern and call it good.
为了在当今典型的 Java + MySQL 应用程序中简单起见,我或多或少会忽略自动提交设置,使用 open-session-in-view 模式并称其为好。
I would strongly discourage explicit RDBMS row locks and use optimistic locks instead. Hibernate offers built-in support for optimistic locks, but it's an easy pattern to adopt even for hand-rolled code and offers better performance.
我强烈建议不要使用显式 RDBMS 行锁,而是使用乐观锁。Hibernate 提供了对乐观锁的内置支持,但它是一种易于采用的模式,即使是手动代码也能提供更好的性能。
回答by nate c
Commit-mode changes the way the db holds locks.
提交模式改变了数据库持有锁的方式。
It is advisable to disable the auto-commit mode only during the transaction mode. This way, you avoid holding database locks for multiple statements, which increases the likelihood of conflicts with other users.
建议仅在事务模式期间禁用自动提交模式。这样,您可以避免为多个语句持有数据库锁,这会增加与其他用户发生冲突的可能性。
...
...
To avoid conflicts during a transaction, a DBMS uses locks, mechanisms for blocking access by others to the data that is being accessed by the transaction. (Note that in auto-commit mode, where each statement is a transaction, locks are held for only one statement.)
为避免事务期间发生冲突,DBMS 使用锁,即阻止其他人访问事务正在访问的数据的机制。(请注意,在自动提交模式下,每个语句都是一个事务,只为一个语句持有锁。)
http://download.oracle.com/javase/tutorial/jdbc/basics/transactions.html
http://download.oracle.com/javase/tutorial/jdbc/basics/transactions.html
回答by BalusC
Only reasonable reason I can see is to get rid of the connection.commit()
and connection.rollback()
boilerplate in simple single-query transactions in small applications. JDBC in raw form requires by itself already a lot of boilerplate. Every line less makes JDBC less scary to starters.
我能看到的唯一合理的原因是在小型应用程序的简单单查询事务中摆脱connection.commit()
和connection.rollback()
样板。原始形式的 JDBC 本身就需要很多样板文件。每一行都减少了 JDBC 对初学者的恐惧。
回答by Brian Knoblauch
95% of the codebase I'm working with now involves single updates where having autocommit on is perfectly reasonable. So, we default to it on. Only turning it off long enough to do the sections of code that need to be a transaction, then autocommit goes right back on!
我现在使用的代码库的 95% 涉及单个更新,其中自动提交是完全合理的。所以,我们默认开启。仅将其关闭足够长的时间来执行需要成为事务的代码部分,然后自动提交会立即重新启动!
回答by Jay
I almost always run with autocommit=true. 99% of the time, my updates are atomic. Sure, there are cases where if you write the debit and then fail trying to write the credit you want to rollback. But in my experience, these are relatively rare. Usually each record that I write stands on its own. In that case, not needing to bother with doing a commit after each write is convenient. It save a line of code here and there. It may save more than that if, given the structure of the program, it means I don't need an additional try/catch block or that I don't need to pass a connection object between functions. It saves on annoying bugs where someone forgot to do a commit.
我几乎总是使用 autocommit=true 运行。99% 的时间,我的更新都是原子的。当然,在某些情况下,如果您写入借方,然后尝试写入要回滚的贷方失败。但以我的经验,这些比较少见。通常我写的每条记录都是独立的。在这种情况下,不需要在每次写入后进行提交很方便。它在这里和那里保存一行代码。如果给定程序的结构,这意味着我不需要额外的 try/catch 块或者我不需要在函数之间传递连接对象,那么它可能会节省更多。它可以避免有人忘记提交的烦人错误。
The only way I see that it could "lure someone into trouble" is he decides that turning autocommit off and doing the commit or rollback is too much trouble and so he does updates that should be within a transaction individually. Then everything apears to work fine as long as nothing happens that should abort the transaction. If test scenarios are inadequate, I could imagine this slipping into production.
我认为它可能“引诱某人陷入困境”的唯一方法是他决定关闭自动提交并执行提交或回滚太麻烦,因此他单独执行应在事务中进行的更新。然后,只要没有发生应该中止交易的事情,一切都会正常工作。如果测试场景不充分,我可以想象这会进入生产阶段。
But you could say the same about almost any feature of a language. Like, suppose you write a program that process numbers that 90% of the time will fit in a long, but every now and then may be bigger. Faced with this situation, the right thing to do is to use BigInteger or create a new class to handle the bigger numbers. A lazy programmer might be lured into using long because it will usually work and other alternatives are too much trouble. Would you therefore conclude that Java should not include long's (or int's) because someone might be lured into using them when they are not appropriate?
但是你可以对语言的几乎所有特性说同样的话。例如,假设您编写了一个程序来处理 90% 的时间适合很长的数字,但有时可能会更大。面对这种情况,正确的做法是使用 BigInteger 或创建一个新类来处理更大的数字。一个懒惰的程序员可能会被引诱使用 long,因为它通常会起作用,而其他替代方法太麻烦了。因此,您是否会得出结论,Java 不应包含 long(或 int),因为当它们不合适时,有人可能会被引诱使用它们?
If in your programs the majority of updates have to be done within a transaction context, then turn autocommit off. Its presence doesn't hurt you any. It's there for when it's convenient, but when it's not you can turn it off.
如果在您的程序中,大多数更新必须在事务上下文中完成,那么请关闭自动提交。它的存在不会伤害你任何。它在方便时就在那里,但在不方便时您可以将其关闭。
回答by Thomas W
Auto-commit is convenient; but with changes to the JDBC 3 spec, has become much less useful.
自动提交很方便;但是随着 JDBC 3 规范的变化,它变得不那么有用了。
Since JDBC 3connections in "auto-commit" mode can't have more than one Statement open. Executing another statement, will close the first -- including any ResultSet.
由于“自动提交”模式下的 JDBC 3connections 不能打开多个语句。执行另一个语句,将关闭第一个——包括任何 ResultSet。
Thus, looping within a SELECT and issuing UPDATEs (or even nested SELECTs) will tend to fail. Apparently it's a crime, to actually want to do somethingwith the results of your outer SELECT!
因此,在 SELECT 中循环并发出 UPDATE(甚至嵌套的 SELECT)往往会失败。显然这是一种犯罪,实际上想要对外部 SELECT 的结果做一些事情!
Anyway, depends on the specific driver & version.. but in general the JDBC 3 spec appears to mandate this unhelpful behaviour. Upgrading drivers can also unhelpfully 'discover' this behaviour.
无论如何,取决于特定的驱动程序和版本......但总的来说,JDBC 3 规范似乎强制要求这种无益的行为。升级驱动程序也可能无益地“发现”这种行为。
Why use auto-commit? Originally, it was helpful & convenient. As other answers say, JDBC requires copious amounts of GUFF and HANDLING to call correctly.. JDBC is not really a well-designed API :(
为什么要使用自动提交?最初,它很有帮助且方便。正如其他答案所说,JDBC 需要大量的 GUFF 和 HANDLING 才能正确调用。JDBC 并不是真正设计良好的 API :(
These days, you'd be better using Hibernate or Spring's JdbcTemplate.. And if you're doing servlets/web apps, place your transaction management (begin/end) or Hibernate session (bind it to a thread-local) at the boundaries of the "User Request".
这些天,你最好使用 Hibernate 或 Spring 的 JdbcTemplate ..如果你正在做 servlets/web 应用程序,把你的事务管理(开始/结束)或 Hibernate 会话(将它绑定到线程本地)在边界的“用户请求”。
eg, get bind your connection/transaction at the start of the ServletRequest; and return it at the end.
例如,在 ServletRequest 开始时绑定您的连接/事务;并在最后返回。
You can use a javax.servlet.Filter or similar, and bind it to a thread-local, make a static helper to get it or requireit, etc.
您可以使用 javax.servlet.Filter 或类似的,并将其绑定到线程本地,创建静态帮助程序以获取或需要它等。
回答by Suresh Vadali
Well there are certain conditions that needs careful look while enabling the “auto-commit” at global level:
好吧,在全局级别启用“自动提交”时,需要仔细查看某些条件:
a.) The transaction management at query level will be left to user, for an instance if one needs bunch of queries to either succeed or fail together then it needs to be wrapped under BEGIN and commit Transaction.
a.) 查询级别的事务管理将留给用户,例如,如果一个人需要一堆查询同时成功或失败,则需要将其包装在 BEGIN 下并提交事务。
b.) Remember, there's no rollback when “auto-commit” is enabled.
b.) 请记住,启用“自动提交”时不会回滚。
c.) There's also an overhead of writing (committing) each and every transaction.
c.) 还有编写(提交)每个事务的开销。
d.) For read only queries there's no explicit need of “auto-commit” but by enabling “auto-commit” it is automatically enforced for all queries.
d.) 对于只读查询,没有明确需要“自动提交”,但通过启用“自动提交”,它会自动对所有查询强制执行。
If table locking is the only concern for enabling the auto-commit then it may not be a good idea, rather one may resort to lower lock timeouts.
如果表锁定是启用自动提交的唯一问题,那么这可能不是一个好主意,而是可以求助于较低的锁定超时。