我正在帮助解决僵局。环境:Tomcat 5.5,Java 5,Microsoft SQL Server 2008,jTDS(替换旧驱动程序)。我们有一个传统的连接池。
数据库代码始终遵循以下方案:
connection = connectionPool.getConnection(); // 1
boolean previousAutoCommitStatus = connection.getAutoCommit(); // 2
connection.setAutoCommit(false); // 3
// ... use the connection ...
// execute prepared statement 4
// execute prepared statement 5
// execute prepared statement 6
connection.commit(); // 7
connection.setAutoCommit(previousAutoCommitStatus); // 8
connectionPool.releaseConnection(connection); // 9
虽然我们捕获了这个错误(原谅:软件缺陷)但我想知道:驱动程序是如何工作的?我的猜测:无论我在(3)和(7)之间做什么都由驱动程序/ DBMS排队。只有当我connection.commit()
DBMS开始一个新事务时,才获取操作所需的每个锁(我希望它足够智能锁定较小的可能对象集),执行语句并释放锁,从而关闭事务。
或者,只要我执行预准备语句,DBMS就会锁定表吗?
编辑:我想要了解的是“commit()”是否在一组以“begin trans / lock table”开头并以“commit / unlock table”结尾的SQL语句中翻译或如果任何Java executeStatement()
立即获得锁定。
TIA
答案 0 :(得分:5)
如果您对内幕细节感兴趣, 在连接上发送SQLServer JDBC实现
发出以下命令
IF @@TRANCOUNT > 0 COMMIT TRAN
@@ TRANCOUNT = 0 - 没有开放交易 @@ TRANCOUNT = 1 - 1个开放交易 @@ TRANCOUNT = 10 - 10开放交易
将自动提交设置为false时,
set implicit_transactions on
这些是MS SQLServer特定命令。
答案 1 :(得分:1)
根据this resource,只要您拨打setAutocommit(false);
我认为它可能仍然依赖于驾驶员,但这将是典型的。另请参阅MSDN,其中也相同。
//Switch to manual transaction mode by setting
//autocommit to false. Note that this starts the first
//manual transaction.
con.setAutoCommit(false);
答案 2 :(得分:1)
connection.setAutoCommit(false);
在数据库服务器上触发“BEGIN TRAN”和
connection.commit();
会触发“COMMIT TRAN”
如果要防止这两个语句之间的锁定,请将连接的隔离级别设置为“Read Uncommited”。在这种情况下,您必须确保它是可接受的。
setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
答案 3 :(得分:0)
完全的内容完全取决于驱动程序的实现,因此您需要查看正在使用的驱动程序的文档以获得明确的答案。
setAutoCommit(false)不一定在数据库上开始事务,并且语句不一定在数据库上执行,甚至在您调用代码中的execute函数时获取锁定,正如您所推测的那样。话虽这么说,据我所知,共享(读)锁通常是在执行语句时获取的;调用commit时更新锁。您可能遇到转换死锁(当多个语句的读锁定在等待转换为写锁时发生),我会检查您的更新语句是否在其中嵌套了可能导致此类锁定的选择。