我是不是需要管理有关数据库访问的并发性?

Posted

技术标签:

【中文标题】我是不是需要管理有关数据库访问的并发性?【英文标题】:Do i need to manage concurrency regarding database access?我是否需要管理有关数据库访问的并发性? 【发布时间】:2014-01-16 21:02:33 【问题描述】:

我有 4 个线程以并发方式运行(在/从数据库中插入/选择行), 我是否必须关心同步访问或H2 Databse 已经有机制来管理线程之间的访问?

PS:Connection conn变量是线程间共享的,所以连接一次,因为我使用的是嵌入式模式,所以只允许一次连接..

干杯。

【问题讨论】:

如果只有一个连接,你必须同步它。 你能解释一下为什么我必须同步它吗,我需要更多关于这个主题的技术信息,谢谢。 【参考方案1】:

这里有两个可能的问题。一个是连接对象是否是线程安全的(意味着并发调用不会使对象处于不良状态),另一个是关于粒度(内置同步是否适合您的需求)。

根据H2's documentation:

线程安全:连接是线程安全的,因为访问是 同步。但是,为了与其他数据库兼容,一个 任何时候都只能在一个线程中使用连接。

就 H2 而言,同时从多个线程访问连接应该没问题。 (它不会很快,因为线程将排队等待获取连接,但连接对象不会由于竞争条件而遭受某种破坏,从而导致事情被破坏。)这里的警告是,如果你想要要将相同的代码与其他数据库一起使用,您不应该像 H2 那样指望其他数据库的同步:即使 JDBC 规范要求连接是线程安全的(它可能,我不记得了),一些驱动程序可能不是合规。

此时,如果您不关心事务并且只需要自动提交(意味着每个 JDBC 调用都是单独提交),那么您就可以了(但是请参阅 Mark R 在 cmets 中关于使用自动提交时结果集关闭的观点)。但是,如果您将多个 JDBC 调用分组到事务中(将 autocommit 设置为 false 并在连接上调用 commit),那么您将需要自己管理对连接的访问​​(让线程以独占方式获取连接,运行 JDBC 语句,然后调用 commit,然后释放连接上的锁),这样您就可以控制事务中的内容。否则,当您在连接上调用 commit 时,不知道哪些线程的工作正在被提交。

最安全的方法是同步访问整个工作单元。考虑让您的线程将它们的 SQL 命令排队,并让它们由对连接具有唯一访问权限的专用线程处理。

【讨论】:

理论上听起来不错,但是当您执行查询并在自动提交中处理结果集时,您需要独占访问权限,否则在同一连接上的另一个线程上执行另一个查询将导致结果设置为关闭(根据自动提交的 JDBC 规范的要求)。一次在一个线程上使用连接更简单、更简单、错误更少。 @Mark:好点,试图将其包含在答案中。稍后我会尝试添加更多细节。【参考方案2】:

DBMS 进行的每个事务都是原子的。因此,如果您只有一个连接 被多个theads使用,您可以确保从DBMS保存 管理并发。

主要问题在客户端,意味着您负责处理 也是服务器的结果集。

这里有一些提示(我的):

- Avoid complex queries which take a lot of time
- use the abbility of multiple connections by creating
  independent clients which communicate with the server.
- look at patterns and anti-atterns concenring this issue

希望对你有帮助

【讨论】:

以上是关于我是不是需要管理有关数据库访问的并发性?的主要内容,如果未能解决你的问题,请参考以下文章

浅谈并发性模型的测试策略

8年Java老鸟讲解, 事务的隔离级别,这篇很通透

Java内存模型对并发处理的三个特性

Java并发编程实战-阅读笔记02-对象的共享

mysql常用命令

并发共享数据