2

I created a deadlock situation by having 2 functions lock 2 rows in a mysql table in opposite orders. I have @Transactional on both functions. I also have an aspectj aspect on both functions that retries the failed one at most 2 more times.

After the deadlock, one thread succeeds and one fails. The failed one retries. So far so good. However, there are 2 problems after this point.

  1. When the failed function was retried a second time, it reads the 2 rows again. However, the value for the first one is old and the second one is new.

  2. At the end, the transaction fails because the transaction was already marked for rollback. So the @Transactional proxy is around the retry proxy. Is there a way to reverse the order? I tried to have the retry proxy inherit Ordered and set the order to Ordered.HIGHEST_VALUE and Ordered.LOWEST_VALUE but neither worked.

Jack Peng
  • 576
  • 5
  • 19

2 Answers2

3

I tried spring retry and it worked like a charm. Still looking into how it does it magic though.

I basically did this:

add dependency on org.springframework.retry spring-retry

add @EnableRetry to application

add @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 2000)) above @Transactional annotated functions.

Jack Peng
  • 576
  • 5
  • 19
0

This one has the more direct answer:

Intercepting @Transactional After Optimistic Lock for Asynchronous Calls in Restful App

Just added @Order(1) below the aspect.

Turned out the key was to use 1 as the order. I tried the Ordered interface again just like in the problem description. This time using 1 and it worked just the same as the Order annotation is just a shortcut to the interface.

Community
  • 1
  • 1
Jack Peng
  • 576
  • 5
  • 19