2016-04-26 3 views
1

Ich versuche Transaktionen mit Spring-Boot, Feder-Daten und MySQL zu verstehen.Get Deadlock beim Ausführen 2 Transaktions-Methode mit Federdaten und Mysql

Ich erstellte Service UpdateService, der zum Aktualisieren von Datensatz in der Datenbank verwendet wird. Methoden ändern und ändern2 wird transaktional ausgeführt.

@Autowired 
private UserRepo userRepo; 

@Transactional(isolation = Isolation.SERIALIZABLE) 
public void change() { 
    User user = userRepo.findOne("Jan"); 

    write("before change", user); 
    sleep(2000); 
    user.setPassword("new password"); 
    write("after change", user); 
} 

@Transactional(isolation = Isolation.SERIALIZABLE) 
public void change2() { 
    User user = userRepo.findOne("Jan"); 

    write("before change2", user); 
    user.setSecondName("new name"); 
    write("after change2", user); 
} 

und wenn ich ändern und change2 Methoden aufrufen, erhalten i-Protokolle:

before change User(name=Jan, secondName=Adam, password=Kowalski) 
before change2 User(name=Jan, secondName=Adam, password=Kowalski) 
after change2 User(name=Jan, secondName=new name, password=Kowalski) 
after change User(name=Jan, secondName=Adam, password=new password) 

und danach auch bekam ich Ausnahme:

com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction 

Meine Frage ist, warum Transaktion change2 beginnt vor der Änderung erledigt? Was ist der Grund für einen Stillstand?

+0

Könnten Sie bitte mehr Kontext geben? dh. Wie werden 'change' und' change2' ausgeführt? Werden sie gleichzeitig ausgeführt? –

+0

Sie werden vom Controller ausgeführt @RequestMapping ("/ ändern") private void change() { updateService.change(); } change2 sieht ähnlich aus Sie werden ausgeführt: Ich exec in Postman ändern und sofort change2 (das ist der Grund, dass ich Schlaf für 2s zu verhindern, um die erste Transaktion abzuschließen, bevor Sekunde starten will) – adrian215

+0

In Ihrem Code nichts verhindert ' change2' um erst nach 'change' zu ​​starten, beende seine Transaktion. Die Methode 'findOne' führt eine Auswahl im' SHARE MODE' durch, die gleichzeitiges Lesen erlaubt. Was ich nicht verstehe, ist der Stillstand. –

Antwort

1

Bellow ist mein Standpunkt:

warum Transaktion change2 beginnt vor der Änderung erfolgt ist?

für MySQL, müssen Sie zunächst über die Version von MySQL, Pflege und this official site url about transaction zu sehen. Speziell ist die Beschreibung der Isolation Level SERIALIZABLE:

  • Dieses Niveau ist wie WIEDERHOLBARE READ, aber InnoDB konvertiert implizit alle Ebene SELECT-Anweisungen ... LOCK IN SHARE MODE wenn autocommitis deaktiviert zu wählen. Wenn autocommit aktiviert ist (Das sagt, der Betrieb lesen von Änderung die Leseoperation von change2 nicht blockieren), ist die SELECT eine eigene Transaktion. Es ist daher bekannt, dass es nur lesbar ist und serialisiert werden kann, wenn es als ein konsistentes (nicht blockierendes) Lesen ausgeführt wird und nicht für andere Transaktionen blockiert werden muss. (Um einen einfachen SELECT zu zwingen zu sperren, wenn andere Transaktionen die ausgewählten Zeilen geändert haben, deaktivieren autocommit.

Was ist der Grund der Sackgasse ist?

Beim Lesevorgang von Änderung und change2 wird ausgeführt, das besagt, dass zwei Transaktionen die Shared Lock in der gleichen Zeile enthalten haben.Wenn Sie den Schreibvorgang von ausführen, ändern Sie (Transaktion t1) und change2 (Transaktion t2), t1 wird auf t2 warten veröffentlicht die Shared Lock und t2 wird auch auf t1 Releases Shared Lock warten, so dass dies zu einem Dead Lock führen wird.

Ich schlage vor, Sie sehen die Transaktions- und Sperrmechanismus von MySQL:

http://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-model.html http://dev.mysql.com/doc/refman/5.7/en/innodb-lock-modes.html

Hoffnung, Ihnen zu helfen.

+0

Vielen Dank, die ich gesucht habe Lösung in JPA. Ich habe nicht erwartet, dass das mysql-Konfiguration war. – adrian215