MySQL ruft zu Beginn jeder Anweisung für jede zu verwendende
Tabelle
handler::external_lock()
auf. Somit wird immer dann, wenn eine Tabelle zum ersten Mal
angesprochen wird, implizit eine Transaktion gestartet.
Da noch keine Sperren vorhanden sind, werden alle Tabellen,
die möglicherweise zwischen dem Anfang und dem Ende einer
Anweisung verwendet werden könnten, gesperrt, bevor die
Ausführung der Anweisung beginnt. Für alle diese Tabellen
wird handler::external_lock()
aufgerufen.
Wenn also ein INSERT
einen Trigger
abfeuert, der eine gespeicherte Prozedur aufruft, die eine
gespeicherte Funktion aufruft usw., werden alle von Trigger,
gespeicherter Prozedur, Funktion usw. verwendeten Tabellen
schon zu Beginn des INSERT
gesperrt. Und
wenn ein Konstrukt wie das folgende vorliegt, dann werden
beide Tabellen gesperrt:
IF .. verwende eine Tabelle ELSE .. verwende eine andere Tabelle
Außerdem gilt: Wenn ein Benutzer LOCK
TABLES
eingibt, ruft MySQL
handler::external_lock
nur ein einziges
Mal auf. In diesem Fall führt MySQL
handler::start_stmt()
zu Beginn der
Anweisung aus.
Das folgende Beispiel zeigt, wie eine Speicher-Engine eine Transaktion starten und Sperranforderungen dabei berücksichtigen kann:
int my_handler::external_lock(THD *thd, int lock_type) { int error= 0; my_txn *txn= (my_txn *) thd->ha_data[my_handler_hton.slot]; if (txn == NULL) { thd->ha_data[my_handler_hton.slot]= txn= new my_txn; } if (lock_type != F_UNLCK) { bool all_tx= 0; if (txn->lock_count == 0) { txn->lock_count= 1; txn->tx_isolation= thd->variables.tx_isolation; all_tx= test(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK)); } if (all_tx) { txn->tx_begin(); trans_register_ha(thd, TRUE, &my_handler_hton); } else if (txn->stmt == 0) { txn->stmt= txn->new_savepoint(); trans_register_ha(thd, FALSE, &my_handler_hton); } } else { if (txn->stmt != NULL) { /* Schreibe Transaktion fest, wenn Autocommit-Modus eingeschaltet */ my_handler_commit(thd, FALSE); delete txn->stmt; // Lösche Savepoint txn->stmt= NULL; } } return error; }
Jede Speicher-Engine muss immer zu Beginn einer Transaktion
trans_register_ha()
aufrufen. Die
Funktion trans_register_ha()
registriert
eine Transaktion beim MySQL Server, um spätere
COMMIT
- und
ROLLBACK
-Operationen möglich zu machen.
Ein weiteres Implementierungsbeispiel für
external_lock()
finden Sie in
ha_innodb.cc
.
Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.