Comment relancer les transactions sur interblocage / lock-timeout au spring?

Quelle est la meilleure pratique pour mettre en œuvre un redémarrage de transaction en cas d’interblocage ou d’exception de délai de locking lors de l’utilisation de Spring (en particulier de l’approche recommandée par Spring: transactions déclaratives)?

Merci,

Asaf

Je pense que Spring lui-même devrait avoir une bonne réponse à cette question (sous forme de documentation, au moins, ou d’un intercepteur de relance quelconque). Hélas, ce n’est pas le cas.

Le meilleur moyen de gérer les tentatives (si vous voulez continuer à être “déclaratif” à propos de choses) est d’écrire votre propre implémentation d’intercepteur qui réessayera automatiquement la transaction un nombre de fois configuré. Pour commencer, étudiez le TransactionInterceptor de Spring, qui gère le comportement start / rollback / commit pour les transactions déclaratives. Si vous utilisez Hibernate, notez la manière dont il gère la liaison / dissociation de session Hibernate avec le thread en cours.

A surveiller si vous utilisez Hibernate:

  • Votre “intercepteur de relance” doit être sûr de dissocier toute session Hibernate liée à un thread préexistante et de relier une nouvelle. Une fois qu’une exception (par exemple, un blocage) est levée à partir du code Hibernate / JDBC, la session Hibernate correspondante est empoisonnée et doit être supprimée. ( session.clear() n’est pas suffisant.)
  • Faites attention si vos méthodes de service transactionnel utilisent des objects de session Hibernate en tant que parameters de méthode. Si vous réessayez, lorsque vous réinitialisez votre session Hibernate, ces objects sont détachés. Vous devrez les rattacher si la méthode de service suppose qu’elles sont attachées (par exemple, si elles utilisent des propriétés chargées paresseuses auxquelles on accède dans la méthode de service, ou si vous essayez de les enregistrer, etc.) En général, il est préférable de n’utilisez pas d’objects Hibernate comme parameters pour les méthodes de service transactionnelles.
  • Vous allez implémenter MethodInterceptor.invoke() – l’instance MethodInvocation qui est transmise à ceci peut être stateful; vous devrez peut-être le cloner avant de l’utiliser dans l’intercepteur.

Je recommande d’utiliser la classe org.springframework.retry.interceptor.RetryOperationsInterceptor partir du projet de nouvelle tentative, configurée comme org.springframework.retry.interceptor.RetryOperationsInterceptor :

      

Mais si vous souhaitez toujours le mettre en œuvre vous-même, l’ exemple de la documentation de spring de AOP est un bon début.

Il n’y a pas de réponse universelle car cela dépend des spécificités de l’application. Par exemple, vous pouvez effectuer un redémarrage automatique de l’opération de transaction ou informer l’utilisateur de l’échec de l’opération et demander une confirmation explicite de la nouvelle tentative, etc.

J’utiliserais AOP en cas de scénario de redémarrage automatique.

J’ai eu la même question il y a plusieurs années et j’ai fini par écrire ma propre solution en tant qu’aspect AOP, qui finit par ressembler à ceci dans votre code:

  @RetryTransaction @Transactional public void doSomething() { .... }