2017-06-27 3 views
0

Ich habe eine Frage zu MySQL und Transaktionen. Ich arbeite mit MySQL 5.7.18, Python 3 und der Oracle MySQL Connector v2.1.4Was ist der Unterschied (in MySQL) zwischen Transaktions-Rollback und nicht Commit?

Ich verstehe nicht den Unterschied zwischen a) eine Transaktion und -Bei Fehler aufweist - und Rollback b) nicht mit Transaktion und - im Fehlerfall - einfach die Änderungen nicht übernehmen.

Beide scheinen mich mit genau den gleichen Ergebnissen verlassen (d. H. Keine Einträge in der Tabelle, siehe Codebeispiel unten). Hat das mit der Verwendung von InnoDB zu tun - würden sich die Ergebnisse sonst unterscheiden?

Was ist der Vorteil der Verwendung einer Transaktion ist, wenn 1) I nicht begangene Änderungen Rollback und 2) ich auch nur die Änderungen konnten nicht begehen (bis ich mit meiner Aufgabe oder sicher fertig bin, dass einige Abfrage nicht erhöhen irgendwelche Ausnahmen)?

Ich habe versucht, die Antworten auf diese Fragen in https://downloads.mysql.com/docs/connector-python-en.a4.pdf zu finden, konnte aber den wesentlichen Unterschied nicht finden.

Jemand fragte eine fast identische Frage und erhielt einige Antworten, aber ich glaube nicht, dass diese tatsächlich eine Antwort enthalten: Mysql transaction : commit and rollback Antworten auf mehrere Verbindungen offen und Sichtbarkeit von Änderungen. Ist das alles da?

import mysql.connector 

# Connect to MySQL-Server 
conn = mysql.connector.connect(user='test', password='blub', 
           host='127.0.0.1', db='my_test') 
cursor = conn.cursor(buffered=True) 

# This is anyway the default in mysql.connector 
# cursor.autocommit = False 

sql = """CREATE TABLE IF NOT EXISTS `my_test`.`employees` (
    `emp_no` int(11) NOT NULL AUTO_INCREMENT, 
    `first_name` varchar(14) NOT NULL, 
    PRIMARY KEY (`emp_no`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8""" 
try: 
    cursor.execute(sql) 
    conn.commit() 
except: 
    print("error") 

# Arguments on default values 
# conn.start_transaction(consistent_snapshot=False, 
#   isolation_level=None, readonly=False) 

sql = """INSERT INTO `my_test`.`employees` 
(`first_name`) 
VALUES 
(%s);""" 

employees = {} 
employees["1"] = ["Peter"] 
employees["2"] = ["Bruce"] 
for employee, value in employees.items(): 
    cursor.execute(sql, (value[0],)) 
    print(conn.in_transaction) 

# If I do not commit the changes, table is left empty (whether I write 
# start_transaction or not) 
# If I rollback the changes (without commit first), table is left empty 
# (whether I write start_transaction or not) 
# If I commit and then rollback, the rollback had no effect (i.e. there are 
# values in the table (whether I write start_transaction or not) 
conn.commit() 
conn.rollback() 

Vielen Dank für Ihre Hilfe im Voraus! Ich schätze es.

Antwort

0

Ich denke nicht begangen zu haben, noch gerollt Blätter zurück, die Transaktion in einem Fahrzustand, in dem es noch Ressourcen wie Sperren halten kann etc

0

Ihre Entscheidung, eine Transaktion zu haben, sollte die zahlreichen Gründe berücksichtigen, einen für mit einschließlich mehrerer Anweisungen, von denen jeder die Datenbank schreibt.

In Ihrem Beispiel glaube ich nicht, dass es einen Unterschied macht, aber in komplizierteren Szenarien benötigen Sie eine Transaktion, um ACID zu gewährleisten.

0

Nun ist es egal, welche Datenbank Sie verwenden, wenn Sie eine Transaktion aufrufen, wird es die Ressource (dh jede Tabelle) sperren, bis die Transaktion abgeschlossen oder zurückgesetzt wird, zum Beispiel wenn ich eine Transaktion schreibe, um etwas einzufügen ein Tabelle Test die Testtabelle wird gesperrt, bis die Transaktion abgeschlossen ist, dies kann zu Deadlock führen, da andere diese Tabelle benötigen ... Sie können es selbst versuchen, öffnen Sie einfach zwei Instanzen Ihres mysql in der ersten Instanz run transaction ohne commit und im zweiten Versuch, etwas auf den gleichen Tisch zu legen ... es wird Ihre Zweifel löschen

0

Transaktionen verhindern, dass andere Abfragen die Daten ändern, während Ihre Abfrage ausgeführt wird. Darüber hinaus kann ein Transaktionsbereich mehrere Abfragen enthalten, so dass Sie ALLE im Falle eines Fehlers zurücksetzen können. Dies ist jedoch nicht der Fall, wenn einige von ihnen erfolgreich ausgeführt werden und nur eine Abfrage einen Fehler verursacht. In diesem Fall können Sie den Vorgang beenden mit teilweise engagierten Ergebnissen, wie JLH sagte.

+0

Vielen Dank für Ihre Antwort. Ich denke aber, ich muss widersprechen - und das ist genau Teil meiner Verwirrung. Eine Transaktion sollte Anweisungen in etwas Unteilbares "bündeln". Also, wenn ich 3 sequentielle Anweisungen (z. B. INSERT INTO) ausführen muss und die zweite fehlschlägt, will ich keine Änderungen in meiner Tabelle/DB (** alles oder nichts **). ** ABER **: Dies ist genau was passiert, wenn ich nur die drei Anweisungen ausführen, ohne sie eine Transaktion zu deklarieren und nur Commit, wenn alle drei erfolgreich abgeschlossen wurden. –

+1

Siehe den obigen Code. Es gibt zwei Datenänderungsanweisungen (cursor.execute). Beide werden genau dann angewendet, wenn ich mich verpflichte. Ob ich explizit schreibe start_transaction oder nicht. Wenn ich nach Ausnahmen/Fehlern suche und die zweite -Anweisung eine Ausnahme auslöst, könnte ich einfach von der Festschreibung absehen. Es würden keine Daten in die Tabelle geschrieben. Obwohl ich die Anweisungen (explizit?) Nicht als Transaktion bündeln würde, sind sie "ziemlich" atomar. Vielleicht kommt meine Verwirrung von Autocommit wird standardmäßig in MySQL aber _off_ standardmäßig in mysql.connector für Python. –

+0

Ahhh - gutes Feedback - Ich frage mich, ob das ist! Bitte aktualisieren Sie mit einem Kommentar, sobald Sie es herausfinden. Im Hinblick auf die Bündelung - Transaktionen sind gute Praxis, weil es explizit ist und nicht von anderen Variablen (wie Standardeinstellungen, Anzahl der Anweisungen, etc.) abhängig ist - und obwohl es in diesem einfachen Beispiel keine Rolle spielt, könnte es komplexer werden Szenarien! –

Verwandte Themen