2011-01-16 4 views
15

folgenden Code, mit Python 2.6.6 und MySQLdb 1.2.2 verursacht Befehle nicht synchron; Sie können diesen Befehl nicht jetzt MySQLdb Ausnahme laufen:Wege zu vermeiden, MySQLsdb "Befehle nicht synchron; Sie können diesen Befehl jetzt nicht ausführen" (2014) Ausnahme

import MySQLdb 

conn = MySQLdb.connect(db="test", user="root") 
cursor = conn.cursor(MySQLdb.cursors.DictCursor) 

cursor.execute("BEGIN; CREATE TABLE t1 (t1_id INT PRIMARY KEY AUTO_INCREMENT); COMMIT;") 
cursor.execute("BEGIN; CREATE TABLE t2 (t2_id INT PRIMARY KEY AUTO_INCREMENT); COMMIT;") 

Die Ausnahme während der Ausführung der zweiten Abfrage erhöht wird. Wie ich gelesen habe, wird die Ausnahme im Allgemeinen durch Einschränkungen der MySQL-C-API-Implementierung verursacht, die die gleichzeitige Ausführung von Abfragen verbieten.

Wenn ich Cursor-Objekt zwischen über zwei Abfragen erstellen, wird das Problem umgangen, aber leider nicht die Lösung scheint nicht perfekt zu mir. Ich habe eine sehr einfache Abstraktion über Datenbankverbindung und Abfrageausführung und würde es vorziehen, den Cursor nach jeder Abfrageausführung nicht neu zu erstellen, da er (so weit ich es verstehe) die aktuelle Transaktion festschreiben und möglicherweise andere Nebenwirkungen haben wird.

Daher meine Frage: Was diese Ausnahme gibt andere Wege zu vermeiden? Wie bereitet man das Cursor-Objekt für die Ausführung der nächsten Abfrage vor? Vielleicht gibt es eine Methode, die von der Python-DB-API erwartet wird, die bei Verwendung anderer Datenbankschnittstellen relativ neutral ist und das Problem im Falle von MySQLdb umgehen wird?

Vielen Dank im Voraus für Ihre Zeit und helfen :)

Edit: Nachdem ich die Frage gestellt, begann ich durch die Python DB API-Spezifikation zu lesen über die Nebenwirkungen von Cursor Zerstörung zu lesen (ich bin begehen über Transaktion nicht mehr so ​​sicher :)) und ich fand folgende, alternative Arbeit um:

cursor.execute("BEGIN; CREATE TABLE t1 (t1_id INT PRIMARY KEY AUTO_INCREMENT); COMMIT;") 
while cursor.nextset() is not None: pass 
cursor.execute("BEGIN; CREATE TABLE t2 (t2_id INT PRIMARY KEY AUTO_INCREMENT); 

Das Problem ist, dass ich weiß nicht, was es zu tun hat (es gibt 1 zweimal und None danach) . Sollte ich in diese Richtung graben? Ich meine, sollte ich das Konzept dieser Sets verstehen, um eine Lösung für mein Problem zu finden?

Antwort

9

DB-API versucht, Transaktionen auf seinem eigenen, Starten eine Transaktion auf dem ersten Befehl und mit seinem eigenen API-Aufruf zu handhaben, es zu begehen, so:

cursor.execute("CREATE TABLE t1 (t1_id INT PRIMARY KEY AUTO_INCREMENT)") 
cursor.commit() 
cursor.execute("CREATE TABLE t2 (t2_id INT PRIMARY KEY AUTO_INCREMENT)") 
cursor.commit() 

Meiner Meinung nach ist dies ein ernst ist, greller Designfehler von Pythons DB-API, was es zu einem ernsthaften Problem macht, Befehle außerhalb von Transaktionen auszuführen und eine angemessene Kontrolle über Transaktionen zu haben, z. Dinge wie SQLite BEGIN EXCLUSIVE TRANSACTION zu verwenden. Es ist, als ob jemand ohne Erfahrung echten Datenbank erlaubt wurde die API zu entwerfen ...

+6

+1, oder Sie können nur auf true an erster Stelle gesetzt __autocommit__ der standardmäßig zu deaktivieren ist; wie diese 'cursor.connection.autocommit (True)',. – mouad

+0

@singularity: Aber wenn Sie das tun, ändern Sie das Verhalten der API auf einem niedrigen Niveau - das kann Sie beißen, wenn Sie die Verbindung beispielsweise an Code von Drittanbietern weitergeben. –

+0

@Glenn Maynard: Nein, es ist nicht, es wird nur aktiviert __autocommit__ Option für die Cursor-Verbindung, die wir in unserem Code erstellt haben :), aktivieren Autocommit kann in einigen Fällen sehr hilfreich sein, wenn wir Echtzeit sparen wollen, anstatt jedes Mal zu tun 'cursor.commit()' ... – mouad

Verwandte Themen