2017-02-15 21 views
1

При использовании Galera я получаю - работает даже отлично, указывая на удаленный БД (а не только на локальный).Тупик только с кластером Galera MYSQL

Caused by: 
com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: 
Deadlock found when trying to get lock; try restarting transaction 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native 
Method) [rt.jar:1.7.0_85] 
    at 
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAcc 
essorImpl.java:57) [rt.jar:1.7.0_85] 
    at 
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstr 
uctorAccessorImpl.java:45) [rt.jar:1.7.0_85] 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526) [rt.jar:1.7.0_85] 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) 
    at com.mysql.jdbc.Util.getInstance(Util.java:386) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1064) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541) 
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002) 
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618) 
    at com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1654) 
    at org.jboss.jca.adapters.jdbc.local.LocalManagedConnection.commit(LocalManagedConnection.java:96) 

Я получаю срабатывает через КДИ событие, обожженного когда-то приходит на очереди JMS, в коде выполнить READ/FIND, как:

entityManager.find(getType(), id, LockModeType.PESSIMISTIC_WRITE); 

чем я обновить объект, и его вложенная коллекция, чем я запустить «обновление», которая сводится к этому (в обновлении дао (в)):

this.lock(myobj); 
this.update(myobj); 

Где замок() делает:

entityManager.lock(entity, LockModeType.PESSIMISTIC_WRITE); 

и update() не включает в себя:

entityManager.merge(entity); 
entityManager.flush(); 

Это происходит только когда я изменить JBoss источник данных конфигурации, чтобы указать на Галера URL - идущий непосредственно к одному (удаленной) БД -> Это не проблема

ответ

1

I не понимаю, почему вы блокируете дважды:

  1. Во-первых, вы блокировки с помощью предложения FOR UPDATE:

    entityManager.find(getType(), id, LockModeType.PESSIMISTIC_WRITE); 
    
  2. Во-вторых, вы заблокируйте myobj:

    this.lock(myobj); 
    
  3. Я заметил, что обновление антишаблоном. Если у вас есть управляемый объект, вам не требуется какое-либо явное обновление. Операция merge предназначена для отдельных объектов. Выезд this article for more details.

Теперь, связанный с тупиком. Вам нужно проверить, какие строки вызывают тупик. Скорее всего, что во время flush, Hibernate также выполняет UPDATE на дочерних объектах.

Поскольку Galera использует оптимистичный подход к блокировке для разрешения конфликтов между несколькими главными узлами, тупик может возникать только в том случае, если две транзакции содержат блокировки и пытаются приобрести друг друга за транзакциями. Таким образом, здесь должно быть как минимум две транзакции. Просмотрите журналы, чтобы увидеть конкуренцию.

+0

Согласен. Кажется «неправильным» пытаться использовать «пессимистический» с Galera. –