7

如果我将连接设置为手动提交,这是否意味着我的进程将锁定数据库?如果我必须执行可能需要 4-5 小时才能执行的多个 SQL 查询,这是否意味着在此期间没有其他用户可以访问我的数据库?

我正在采用 Web 应用程序的场景,其中有成千上万的用户访问同一个数据库。

connection.setAutoCommit(false);
//multiple sql query that will probably take 4-5 hours to be executed

connection.commit();
4

3 回答 3

14

将 autocommit 设置为 false 通常不会对读取产生影响,因此,如果这是您正在运行的查询类型,则应该不是问题。

autocommit=false 保证您将在事务中执行查询(插入、删除、更新),这意味着它们要么全部成功(最后提交),要么失败并被滚动背部。

当您插入、更新或执行 aselect ... for update时,某些行将被锁定,这很难预测,因为它取决于您的引擎、Mysql 版本、隔离级别等。

例如,如果 autocommit=false 并且两个用户需要同时更新相同的行,那么一个用户被锁定,等待第一个用户完成,无论是提交还是回滚。

假设USER1触发了针对 10 行的数据库更新。

您开始交易,进行更新,进行更多查询......

在提交/回滚之前,USER2触发相同的更新,或者将针对USER1正在更新的一个或多个相同行的更新。

USER2将被锁定,等待USER1提交或回滚,然后才能执行更新。

一种测试方法是打开两个不同的数据库连接,例如,通过命令行或其他客户端,并模拟这种行为。将自动提交设置为 false,在一个客户端上进行更新,在第二个客户端上执行相同操作,然后看到它挂在那里,直到您在第一个客户端上提交或回滚。

这种技术可以非常方便地帮助您了解幕后发生的事情。

于 2013-04-23T11:28:54.507 回答
6

connection.setAutoCommit(false); 表示您正在此连接上开始交易。您将在此连接中对数据库表所做的所有更改将在提交时保存或在回滚时恢复(或断开连接而不提交)。这并不意味着您锁定了整个数据库。其他用户是否会在尝试访问您的事务使用的表时被锁定,这取决于您的事务正在执行的操作和事务隔离级别。

于 2013-04-23T11:26:48.017 回答
0

这取决于隔离级别和您在做什么:

如果您正在阅读:

  • 脏读/已提交读:不会影响其他任务
  • 可重复阅读:其他阅读任务不受影响。其他写作任务可能会受到影响。(实施依赖)
  • 序列化:其他阅读任务不受影响,写作任务会受影响。

如果您正在进行更新,其他任务将受到影响。一般来说,您不应该在长时间运行的事务中进行更新。

于 2013-04-23T11:48:37.877 回答