2014-02-15 3 views
4

Пожалуйста, исправьте меня, если я где-то не прав.Что происходит, когда аннотированный метод @Transactional попадает параллельно несколькими экземплярами?

У меня возникла проблема, когда мои транзакции не сохраняются в базе данных, и происходят какие-то гонки, которые закручивают данные. Приложение попадает параллельно несколькими экземплярами. Я использовал @Transactional, который, как я знаю, должен делать транзакцию с базой данных, и транзакция фиксируется при возврате метода.

Вопрос заключается в том, что удары по нему через несколько экземпляров все еще поддерживают эту транзакцию за предмет удара, или он не справляется с ситуацией, и данные будут испорчены из-за гонок?

Может быть предложено решение для данного состояния?

+0

Можете ли вы разместить код? возможно ли, что ваш сервис/dao/instance использует экземпляры? –

ответ

2

@Transactional не имеет отношения к синхронизации. Он просто гарантирует, что ваш поток будет успешным или не удастся. Каждый удар имеет свой собственный поток и собственный успех или неудачу.

Я предполагаю, что вы переживаете из-за использования общих данных.

Например. Если у вас есть класс Foo который выглядит следующим образом:

public class Foo { 
    private static boolean flag = true; 

    @Transactional 
    public void doSomething() { 
     flag = false; 
    } 
} 

В данном случае это не имеет значения, что у вас есть много Foo экземпляров, потому что все они используют один и тот же flag.

Другой сценарий был бы, если у вас есть один экземпляр Foo (очень распространенный, если вы используете что-то вроде Spring), и у вас есть данные, которые были изменены для этого экземпляра. Вы можете посмотреть на то же Foo например, и просто удалить static из flag:

public class Foo { 
    private boolean flag = true; 

    @Transactional 
    public void doSomething() { 
     flag = false; 
    } 
} 

В любом из этих случаев вам нужно синхронизировать изменения данных каким-то образом. Это не имеет никакого отношения к @Transactional.

+0

Если данные, которыми вы управляете напрямую, связаны с tx, тогда может иметь смысл использовать «TransactionSynchronizationManager» Spring и подкласс «TransactionSynchronization». Это гарантирует, что состояние данных соответствует существующему состоянию tx. – AngerClown

2

Это транзакции транзакций базы данных и поведение СУБД зависит, но это, как правило, работает следующим образом:

  1. Нить ввести метод.
  2. Поток вводит тот же или любой другой транзакционный метод. Он не блокирует как @Transactionalне про синхронизацию.
  3. Один поток выполняет любой запрос, который блокирует ресурс базы данных. Например. SELECT * FROM MYTABLE FOR UPDATE;.
  4. Другой поток попробуйте выполнить все, что нужно тот же ресурс базы данных. Например. UPDATE MYTABLE SET A = A + 1;И он блокирует.
  5. Поток, который приобрел замок на шаге завершает транзакционный метод успешно делает неявное совершает или терпит неудачу делает неявное отката.
  6. Заблокированная нить просыпается и продолжается, поскольку теперь она может получить доступный ресурс.
Смежные вопросы