Hibernate: Deadlock gefunden, wenn Sie versuchen zu erhalten lock
Ich bin mit hibernate in meinem Projekt, und ich bin immer zufällig Scheinbare Deadlocks für sehr einfache Datenbank-Operationen.
Es ist eine der Stack-Traces: https://gist.github.com/knyttl/8999006 – Was mich verwirrt, dass die erste Ausnahme ist RollbackException und dann gibt es LockAquisition Ausnahmen.
Das problem tritt oft auf ähnliche Klauseln:
@Transactional
public void setLastActivity() {
User user = em.findById(...);
user.setLastActivity(new Date());
em.merge(user);
em.flush();
}
Bin ich ziemlich festgefahren, da ich nicht weiß, ob es ein problem von Hibernate, MySQL oder C3P0.
Mein Hibernate-Konfiguration:
<prop key="hibernate.dialect">${database.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${database.structure}</prop>
<prop key="hibernate.connection.url">${database.connection}</prop>
<prop key="hibernate.connection.username">${database.username}</prop>
<prop key="hibernate.connection.password">${database.password}</prop>
<prop key="hibernate.connection.driver_class">${database.driver}</prop>
<prop key="hibernate.connection.shutdown">true</prop>
<prop key="hibernate.connection.writedelay">0</prop>
<prop key="hibernate.connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
<prop key="hibernate.show_sql">${database.show_sql}</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.ejb.metamodel.generation">disabled</prop>
<!-- Use the C3P0 connection pool provider -->
<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.c3p0.min_size">0</prop>
<prop key="hibernate.c3p0.max_size">50</prop>
<prop key="hibernate.c3p0.timeout">120</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.max_statementsPerConnection">0</prop>
<prop key="hibernate.c3p0.maxStatementsPerConnection">0</prop>
<prop key="hibernate.c3p0.idle_test_period">120</prop>
<prop key="hibernate.c3p0.acquire_increment">1</prop>
<prop key="hibernate.c3p0.numHelperThreads">8</prop>
EDIT1:
- Ich oben schrieb, gab es Scheinbare Deadlocks geschieht - das war falsch, nur ein "Deadlock gefunden, wenn Sie versuchen zu erhalten lock" passieren.
EDIT2:
Dies geschieht auch auf diese Methoden - diese BEDÜRFNISSE werden annotiert mit @Transactional:
@Transactional
public void setLastActivity() {
em.insertNative("table")
.values(...)
.execute();
}
- Sie brauchen, um mehr details zu liefern, wie die tatsächliche Ausnahmen, die Sie immer mit stacktrace. Hier meine ich, nicht auf eine externe Website, die blockiert werden durch Unternehmens-firewalls.
- Sie wahrscheinlich wollen, setzen Sie autocommit=false.
- Gimby: Der stacktrace ist gegeben - sehen eher vorsichtig. brettw: Können Sie uns mehr Informationen, warum sollte es helfen?
- Sie verwenden den Begriff "Scheinbarer Deadlock", aber das scheint nicht in Ihrem Kern. sehen Sie, SCHEINBARER DEADLOCK-Meldungen von c3p0 irgendwann? wenn dem so ist, können Sie reproduzieren, dass mit den langen status-Nachricht folgt?
- Können Sie zeigen Sie Ihren code. Wie Sie öffnen und schließen Sie eine Sitzung/Transaktion.
- Steve: Bitte siehe meine edits. Zeus: Sehen Sie den bearbeiteten code - es geschieht in diesem einfachen Methoden.
- Was passiert, wenn Sie loszuwerden, die @Transactional? Hatte deadlocks mit hibernate vor kurzem wegen @Transactional-Annotationen.
- einige Geschäfte in der Anwendung könnte sein, die sperren halten für eine lange Zeit, Erhöhung der Quote von deadlock. Transaktional verwendet wird, mit " nicht-Standard-isolation irgendwo? Auch könnten Sie nach dem code, code FollowRemote.getFollowsFor, und die Zeile 186 in dieser Methode erwähnt im stacktrace
- es ist etwas seltsam, in der setLastActivity Methode, Nutzer einer angeschlossenen Einheit, so gibt es keine Notwendigkeit, es zu verschmelzen als die Verschmelzung hat keine Auswirkungen auf angeschlossene Einheiten. Auch flush kurz vor dem Ende der Methode nicht benötigt wird, wie der Frühling wird, machen den flush für uns. Gibt es einen speziellen Grund, warum das manuelle Spülen wird? es könnte im Zusammenhang
- Jan Vladimir Moster: Auch wenn ich es entfernt, ich war immer "Keine Transaktion ist im Gange." Ausnahmen – ich dachte, dass beim Zugriff auf entity-manager, da muss immer ich die Transaktion?
- jhadesdev: In der Methode, es gibt nur einfache select-Anweisung, und die Methode ist nicht @Transactional.
- Es scheint, dass, wenn ich rufe native SQL-update, die Methode muss annotiert werden, die mit @Transactional, sonst bin ich immer:
Executing an update/delete query
Ausnahmen. - was ist Ihre Isolationsstufe der Transaktion , ist diese Multi-Thread-Umgebung ? haben Sie sah in die Datenbank , gibt es keine Sperre in diesem moment ?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Weil die Blockaden so Häufig geschehen, wie es aussieht, einige der threads der Anwendung sind sperren für einen längeren Zeitraum.
Jeder thread in der Anwendung, es ist eine eigene Datenbank-Verbindung/verbindungen beim Zugriff auf die Datenbank, also aus Sicht der Datenbank ein, zwei threads zwei verschiedene clients, die im Wettbewerb für Datenbank-locks.
Wenn ein thread sperren für einen längeren Zeitraum und erwirbt Sie in einer bestimmten Reihenfolge, und einen zweiten thread kommt den Erwerb der gleichen sperren, aber auf eine andere Reihenfolge Sackgasse ist vorprogrammiert (siehe hier für details auf diese häufige deadlock führen).
Auch deadlocks auftreten, die bei read-Operationen, was bedeutet, dass einige threads den Erwerb von lese-sperren. Dies geschieht, wenn die threads ausgeführt werden Transaktionen in
REPEATABLE_READ
- Isolationsstufe oderSERIALIZABLE
.Um dieses Problem zu lösen, versuchen Sie die Suche nach Verwendungen von
Isolation.REPEATABLE_READ
undIsolation.SERIALIZABLE
im Projekt, um zu sehen, wenn diese verwendet wird.Als alternative, verwenden Sie die Standard -
READ_COMMITTED
isolation-level und kommentieren die Personen mit@Version
Griff Parallelität mit optimistic locking statt.Auch versuchen zu identifizieren, die Transaktionen mit langer Laufzeit, das passiert manchmal, wenn die
@Transactional
ist an der falschen Stelle und wickelt beispielsweise die Verarbeitung einer ganzen Datei in das Beispiel für eine batch-Verarbeitung, anstatt das zu tun, Transaktionen, Zeile für Zeile.Diese eine log4j-Konfiguration-log erstellen/löschen von entity-Manager und Transaktionen begin/commit/rollback:
Update-Abfragen möglich sind, die über native Abfragen oder JPQL.
Methoden ohne
@Transactional
Abfragen ausgeführt werden, in einem eigenen entity manager und kehren nur freistehende Einheiten, als dich-Sitzung wird daraufhin sofort geschlossen, nachdem die Abfrage ausgeführt wird.also die lazy-Initialisierung Ausnahmen in Methoden ohne
@Transactional
normal ist. Sie können diese zu@Transactional(readOnly=true)
als gut.Dies ist der Fehler mit MySQL.
Der einfachste Weg, um zu beheben & vermeiden von deadlocks ist die Reihenfolge der DB-Operationen geschieht in der Anwendung.
Deadlock tritt meistens auf, wenn mehr als eine Ressource/Verbindung versuchen, zu erwerben, mehr als eine Sperre, die an entgegengesetzten Aufträge, wie folgt:
In das Szenario, wenn beide verbindungen gleichzeitig ausgeführt, Verbindung 1 wird die Sperre auf die Taste(1) und Verbindung 2 auf-Taste(2). Nach, dass sowohl die verbindungen warten, für andere um Sie zu entriegeln auf die Taste. Dies resultiert in deadlock.
Aber ein wenig zwicken in der Reihenfolge der Transaktionen, dann können deadlocks vermieden werden.
Oben re-order ist deadlock Beweis.
Andere Möglichkeiten, um deadlocks zu vermeiden, ist eine Transaktion-management-Mechanismus. Transaktions-management von Frühling ist fast plug-n-play. Darüber hinaus können Sie eine deadlock-wiederholen-Politik im Ort. Eine interessante deadlock Wiederholung über Spring AOP können gefunden werden hier. Auf diese Weise müssen Sie nur fügen Sie die annotation an der Methode, die Sie wollen zu wiederholen, im Falle von deadlock.
Weitere debug-Protokolle auf deadlock, um herauszufinden, welche Aussagen sind verdächtig, versuchen Sie die "show engine innodb status" Diagnose. Außerdem können Sie einen Blick auf Umgang mit Deadlocks.
UPDATE: EIN Szenario für deadlocks in der Transaktions-DB-Operationen.
In einer transaktionalen Datenbank, ein deadlock passiert, wenn zwei Prozesse jeweils eine eigene Transaktion, die updates zwei Zeilen von Informationen, sondern in das Gegenteil um. Zum Beispiel, der Prozess Eines updates der Zeile 1, dann Zeile 2 in der genauen zeitlichen Rahmens, der Prozess B aktualisiert die Zeile 2, dann Zeile 1. Prozess A kann nicht abgeschlossen werden die Aktualisierung von Zeile 2 bis Prozess B beendet ist, aber es nicht beenden kann, die Aktualisierung von Zeile 1 bis Prozess A beendet ist. Egal wie viel Zeit verstreichen zu lassen, diese situation wird sich nie von selbst lösen, und weil dieses Datenbank-management-Systeme wird in der Regel töten die Transaktion der Prozess, von dem die geringste Menge an Arbeit.
Shishir