lyn*_*nks 12 java sql postgresql multithreading transactions
我正在使用JDBC与我的Postgres数据库交谈.如果我的整个应用程序都运行一个连接,即只有一个呼叫;
DriverManager.getConnection("jdbc:postgresql://host:5432/database", user, pass);
Run Code Online (Sandbox Code Playgroud)
但是这个Connection
对象在Java中的多个线程之间共享,我是否正确地假设任何使用SQL事务(BEGIN
和COMMIT
样式)的尝试只会非常混乱和破坏,因为Java线程可能会交错?请问Connection
对象"知道"哪些Java线程使用它来进行查询?
我应该Connection
每个Java线程有一个对象并以这种方式使用SQL事务吗?或者我应该在Java中执行所有事务隔离synchronized
吗?
Cra*_*ger 14
只是详细说明现有的答案:
PgJDBC的Connection
对象是线程安全的,但仅限于语句级别.在自动提交模式下由多个线程使用时,它不会崩溃或产生错误的结果,但它不会为您隔离不同的线程事务.根据文档,您需要使用连接池.
实际上有很多方法可以在多个线程之间使用连接:
使用内部连接池从中获取连接,使用它们执行工作,并将它们返回到池中.对于大多数应用程序来说,这是一个非常可取 Java存在许多JDBC连接池实现,因此不要自己滚动.dbcp和c3p0是两种流行的实现,但如果您使用的是servlet环境或应用服务器,则通常应使用服务器的连接池而不是自带连接池.
使用像pgbouncer或pgpool-II这样的外部连接池,并自由打开/关闭它.这稍微慢一点,并且主要是在应用程序无法或由于各种原因不应在内部池连接时使用的选项.您可能不需要这样做,除非您需要限制数据库的总连接数并在多个应用程序或应用程序实例之间共享它们.
不使用游泳池和自由打开/关闭连接.这非常低效.不要这样做.
使用线程本地存储保持每个线程的连接.这样做可行,但效率极低,因为每个开放连接在空闲时占用数据库服务器资源.除非您在事务池模式下使用像PgBouncer这样的外部连接池,否则不要这样做,在这种情况下它没关系.
仅使用单个连接并在synchronized
块中包装事务,在Connection
实例上进行同步.这将有效并将有效地使用数据库连接,但会限制线程的性能.除了玩具/便利应用之外,它通常不是一个好的设计.
仅使用具有自己专用线程的单个连接.是否有其他连接通过FIFO队列,生产者/消费者样式传递描述要对该线程完成的工作的数据结构.如果线程花费大部分时间来处理CPU繁重或其他非数据库工作并且仅需要有限的数据库访问,则此方法可行.使用它而不是使用连接池的唯一原因是,如果由于某些外部原因而限制使用单个连接,但如果你是,那么它可能是一个不错的选择.
但是,一般情况下,您应该只使用连接池并完成它.
我是否正确地假设任何使用SQL事务(
BEGIN
和COMMIT
样式)的尝试只会非常混乱和破坏,因为Java线程可能会交错?
这是绝对正确的.
Connection对象是否"知道"哪个Java线程正在使用它来进行查询?
不,不是的.
我应该为每个Java线程都有一个Connection对象并以这种方式使用SQL事务吗?
是的,这是一种做法."每线程连接"分配的缺点是可能会打开比您需要的更多连接,从而导致资源的次优使用.您也可以仅在线程需要时打开连接,并在线程完成RDBMS访问后关闭它.如果您使用此路由,请确保使用连接池以减少多次重新打开连接的开销.
归档时间: |
|
查看次数: |
5568 次 |
最近记录: |