简体   繁体   English

仅与 Galera MYSQL 集群发生死锁

[英]Deadlock only with Galera MYSQL cluster

When using a Galera, I am getting - works even fine, when pointing to a remote DB (not just local).使用 Galera 时,当指向远程数据库(不仅仅是本地数据库)时,我得到 - 甚至可以正常工作。

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)

I get triggered via CDI event, fired when something arrives on a JMS queue, in the code I perform a READ/FIND, like:我通过 CDI 事件触发,当有东西到达 JMS 队列时触发,在我执行 READ/FIND 的代码中,例如:

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

than, I update the object and its nested collection, than I run an "update", which boils down to this (inside the DAO's update()):比,我更新对象及其嵌套集合,然后运行“更新”,归结为(在 DAO 的 update() 中):

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

Where lock() does:锁定()在哪里:

entityManager.lock(entity, LockModeType.PESSIMISTIC_WRITE);

and update() combines:update()结合:

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

It's only happening when I change my JBoss datasource config to point to a Galera URL - going directly to one (remote) DB -> no problem只有当我将 JBoss 数据源配置更改为指向 Galera URL 时才会发生这种情况 - 直接转到一个(远程)数据库 -> 没问题

I don't understand why do you lock twice:我不明白你为什么要锁定两次:

  1. First, you are locking using the FOR UPDATE clause:首先,您使用FOR UPDATE子句进行锁定:

     entityManager.find(getType(), id, LockModeType.PESSIMISTIC_WRITE);
  2. Second, you lock the myobj :其次,你锁定myobj

     this.lock(myobj);
  3. I noticed that update Anti-Pattern.我注意到更新反模式。 If you have a managed entity, you don't need any explicit update.如果您有托管实体,则不需要任何显式更新。 The merge operation is meant for detached entities. merge操作适用于分离的实体。

Now, related to the deadlock.现在,与僵局有关。 You need to check which rows are causing the deadlock.您需要检查哪些行导致死锁。 Most likely that during flush , Hibernate executes an UPDATE on the child entities as well.很可能在flush期间,Hibernate 也会对子实体执行 UPDATE。

Since Galera uses an optimistic locking approach to resolving conflicts across multiple Master nodes, the deadlock can only occur if two transactions hold locks and try to acquire each other transaction locks.由于 Galera 使用乐观锁的方式来解决跨多个 Master 节点的冲突,只有当两个事务持有锁并试图获取彼此的事务锁时才会发生死锁。 So, there must be at least two transactions involved here.因此,这里必须至少涉及两个事务。 Check out the logs to see the contention.查看日志以查看争用情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM