简体   繁体   中英

Should a single thread only acquire a single connection from a connection pool?

I am using ORMLite (Java) with HikariCP and I have a lot of code that's called asynchronously ie CompletableFuture.supplyAsync(Supplier). Inside a Supplier I have various calls to different ORMLite Dao objects inside these tasks. I ran into a deadlock scenario and found that increasing the size of the connection pool seemed to have fixed the issue.

After some research, I found that this is a well-documented problem. Having looked at the information provided here :

"Each thread is waiting for a second database connection, and none would become available since all threads are blocked."

This caught my eye. When looking at the ORMLite source code, I found that for each Dao method called, a connection is acquired. In my case, I am calling multiple Dao methods in each asynchronous task I create via CompletableFuture which brings me to my question.

My understanding is that I should only acquire a single connection in each thread so is there a way to do this with ORMLite? Bearing in mind I have calls to different Dao objects and having done some further research, Dao#callBatchTasks(Callable) caught my eye but I am unsure whether I can have calls to different Dao objects inside the Callable. Or is there a flaw in my logic or something fundamental I am missing in my write-up?

I found that for each Dao method called, a connection is acquired

If ORMLite needs to go to the database, it needs to get a connection, right? Is there something that it is not doing right?

My understanding is that I should only acquire a single connection in each thread so is there a way to do this with ORMLite?

I don't think that there is anything that says that a thread can't open multiple database connections. As long as they are all closed when you are done with te operation, then I think this is fine. If you are querying different DAOs that all live on the same database then you can actually reuse the connection each time as long as you are done with it. Ie if you are paging across the results using an open connection then in the middle query another table, then this might screw up the cursor. However, if you do a dao1.queryAll() and then a dao2.queryAll() , this can use the same connection since the first query will have finished.

But if you are using a connection pool, the pool should do the connection management for you with help from ORMLite's ConnectionSource. The pool is supposed to create a new one for you if needed and otherwise reuse old connections. It's a bit strange to have a limit on your database connections.

Dao#callBatchTasks(Callable) caught my eye but I am unsure whether I can have calls to different Dao objects inside the Callable.

You can call different dao objects as long as they are all on the same database. You actually could call a dao with connections to a different database, but you'd have no guarantee around transactions between the databases.

For example if you did something like the following.

  1. You call dao1.callBatchTasks(callable)
  2. In your Callable , you call dao2.delete(entity1) which works.
  3. Still in the Callable , you call dao2.delete(entity2) which throws.
  4. The dao1 transaction will be rolled back, but the entity1 would still be deleted.

The scenario you quoted in the statement

Each thread is waiting for a second database connection, and none would become available since all threads are blocked.

would result in a deadlock only when a thread is holding a lock to connection A AND trying to acquire Connection B, which might be held by another thread which might be trying to get hold of Connection A. As long as you are not "holding" one resource while trying to "grab" the other one, you should be good.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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