We have a service method which does approximately the following:
@Transactional
public void serviceMethod(...){
for(Item i : bunchOfItems){
webServices.webServiceCall(...);
dao.daoUpdateMethod(...);
}
}
The problem is that as soon as an update occurs the DB is holding a lock on the table for the duration of the Transaction开发者_开发知识库 (webservice calls average 5 sec each). Any exception in a webservice call or DAO call should, of course, cause a full rollback.
What's the best approach to this situation?
If the web service call doesn't depend on what you might have updated in a previous iteration, you could make all your web service calls in a first pass and collect the results in memory, and then start a transaction for all your updates. This would make your transaction much shorter and, since I assume the web service call isn't transactional anyway, it wouldn't affect the coherence of your data.
Because I assume the webservice call is not transactional in any way, you can do all webservice calls before you start the transaction to store something.
You can do the whole stuff in different ways:
- sequential - 2 loops, one transaction and a bit memory: loop trough all webservice invocation store the results in an array, open the transaction and then loop trough all results and store them
- sequential - one loop, and n transaction: in the loop, first call the web service for one item, then start a new transaction and store it (loop end)
- in parallel - do the web service invokation in parallel - you can combine it with the two ways mentioned above like JB Nizet suggested his answer
By employing MVCC mode in the database I can avoid locking on updates altogether. After doing this I can perform the same test without any lock contention.
MVCC mode allows reads to occur while an uncommitted update is still in progress.
精彩评论