简体   繁体   English

是否可以在单个JDBC连接上多路复用多个只读事务

[英]Is it possible to multiplex multiple read-only transactions on a single JDBC Connection

Firstly, I have given few data points. 首先,我给出的数据很少。
Next will be the problem described. 接下来将描述问题。


DATA POINTS: 数据点:
[D1] In Hibernate and Annotation and managed objects world, what i have seen a common pattern like [D1]HibernateAnnotationmanaged objects世界中,我看到了一种常见的模式,例如

@Transactional
public void createStuff(..){
// get entity manager and call persist and other operatation
}
@Transactional
public SomeDtoObject getStuff(..){
// get entity manager and call find and getter to polulate a object to return
}

In managed beans the Hibernate transaction is started and commited when we call this methods. 在托管bean中,当我们调用此方法时,将启动并提交Hibernate事务。

Hibernate doc says ( link ): Hibernate文档说( 链接 ):

The most common pattern in a multi-user client/server application is session-per-request. 在多用户客户端/服务器应用程序中,最常见的模式是每次请求会话。

[D2] Also it is advised that connection to database should be pooled using connection pool library C3P0 as stated on postgres documentation ( link ): [D2]此外,建议使用postgres文档( 链接 )上所述的连接池库C3P0来池化与数据库的连接:

Pg will usually complete the same 10,000 transactions faster by doing them 5, 10 or 20 at a time than by doing them 500 at a time. Pg通常一次完成5、10或20次会比一次完成500次更快地完成相同的10,000个事务。

[D3] Also with JDBC [D3]同样使用JDBC
Given a single connection we can run one transaction at a time and as many statement as we like within that transaction. 给定一个连接,我们可以一次运行一个事务,并且可以在该事务中运行任意数量的语句。
Its upto the application(C3P0) to make sure that two different thread executing two different transactional method should not use same connection and one should wait before calling the other method . 取决于应用程序(C3P0),以确保执行两个不同事务方法的两个不同线程不应使用相同的连接,并且一个应在调用另一个方法之前等待。


Problem: 问题:
Now if we use the managed bean transaction pattern using annotation along with a connection pool( Let say only with 1 connection ) with hibernate and session-per-request 现在,如果我们使用带注释的托管bean事务模式以及带有休眠和每次请求会话数的连接池( 仅说1个连接
Also let say the code is something like 还可以说代码就像

@Transactional
public SomeDtoObject getStuff(..){
// get entity manager and call find and getter to polulate a object to return
SomeEntity se = entityManager.find(someentity, primaryKey);
//create Dtos
// access someEntity to all over this method to create SomeDtoObject that we have to return.
// also may access some file on system to fetch some data is order to populate someDtoObject.
// overall let say the method take 150 milli second to do all its work
}

Now imagine there are two different thread( T1 , T2 ) called for getStuff(...) T1 will enter the method and will acquire jdbc connection from connection pool. 现在,假设有两个不同的线程( T1T2 )调用getStuff(...) T1将进入该方法并从连接池获取jdbc连接。
And when T2 will reach entityManager.find the C3P0 will check that there is no connection left it will put T2 on hold till T1 complete the execution which will take around 150 milli second. T2到达entityManager.findC3P0将检查是否没有连接,它将使T2处于保持状态,直到T1完成执行,这大约需要150毫秒的时间。

Ideally, Given that getStuff(...) is going to do read only querys, both thread can use same connection and dont hold thread from executing queries. 理想情况下,假设getStuff(...)将执行只读查询,则两个线程可以使用相同的连接,并且不保留执行查询的线程。
In above case we are keep that connection idle and also keeping the thread to wait. 在上述情况下,我们保持该连接空闲,并保持线程等待。

MAIN QUESTION 主要问题
Is there a way i can say to hibernate that a particular hibernate transaction is readonly and hibernate can then reuse an already acquired connection instead of asking for a new connection from the connection pool ? 我是否可以说一种方式休眠,即特定的休眠事务是只读的,然后休眠可以重用已经获取的连接,而不是从连接池中请求新的连接?


Few solution found/suggested:(not convincing) 很少找到/建议解决方案:(不令人信服)

1 If you are so much worried, dont use transaction using annotation, use hibernate session yourself..... no i like that pattern :) 1如果您非常担心,请不要使用带有注释的事务,而要自己使用休眠会话.....不,我喜欢这种模式:)
2 Hibernate provide a ConnectionRelease link option which can be set to after_statement . 2 Hibernate提供一个ConnectionRelease 链接选项,可以将其设置为after_statement
First Hibernate C3P0 connection pool provider does not support after_statement. 第一 Hibernate C3P0连接池提供程序不支持after_statement。
Second it will be a overhead just release and reacquire a connection. 其次 ,释放并重新获取连接将产生开销。

You cannot multiplex transactions coming from different threads to a one JDBC connection. 您不能将来自不同线程的事务多路复用到一个JDBC连接。 Even if the JTA spec says that this might be possible, in reality, this doesn't happen, and the JDBC drivers are synchronous. 即使JTA规范说这是可能的,但实际上并没有发生,并且JDBC驱动程序是同步的。

Neither 1) and 2) and the right suggestions for your needs. 1)和2)都没有,也没有适合您需求的建议。

  1. You should be using the underlying platform transactional support (eg Java EE, Spring), instead of managing transaction boundaries yourself. 您应该使用基础平台事务支持(例如Java EE,Spring),而不是自己管理事务边界。
  2. The after_statement incurs some penalty , while it still binds the transaction to a connection. after_statement 产生一定的惩罚 ,尽管它仍将事务绑定到连接。

So, the viable alternatives are: 因此,可行的替代方案是:

  1. Reduce transaction time as much as possible so that you can execute a lot of transactions per database connection. 尽可能减少事务处理时间,以便每个数据库连接可以执行许多事务处理。
  2. Increase available read-only connections by using master-slave database replication and route read-only transactions to slaves. 通过使用主从数据库复制来增加可用的只读连接,并将只读事务路由到从属。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM