2011-01-16 16 views
15

Il seguente codice, utilizzando python 2.6.6 e MySQLdb 1.2.2 causa Comandi non sincronizzati; non è possibile eseguire questo comando ora eccezione MySQLdb:Metodi per evitare "Comandi non sincronizzati di MySQLdb, non è possibile eseguire questo comando ora" (2014) eccezione

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;") 

L'eccezione viene sollevata durante l'esecuzione della seconda query. Come ho letto, l'eccezione è generalmente causata dalle limitazioni dell'implementazione dell'API C di MySQL, che non consentono l'esecuzione concomitante di query.

Se si ricrea oggetto cursore tra due query precedenti, il problema viene risolto ma sfortunatamente la soluzione non mi sembra perfetta. Ho un'astrazione molto semplice sulla connessione al database e l'esecuzione di query e preferirei non ricreare il cursore dopo l'esecuzione di ogni query, poiché (a quanto ho capito) commetterà la transazione corrente e potenzialmente avrà altri effetti collaterali.

Pertanto, la mia domanda è: quali sono altri modi per evitare questa eccezione? Come preparare l'oggetto cursore per l'esecuzione della prossima query? Forse c'è qualche metodo previsto dall'API Python DB, che sarebbe relativamente neutrale quando si usano altre interfacce di database e si aggirerebbe il problema in caso di MySQLdb?

Grazie in anticipo per il vostro tempo e aiuto :)

Edit: dopo che ho postato la domanda, ho iniziato a leggere attraverso l'API specifiche di Python DB per leggere gli effetti collaterali di distruzione di cursore (io sono non così sicuro di transazione commetto più :)) e ho trovato seguito, il lavoro alternativo attorno:

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); 

Il problema è che io non so che cosa fa (si restituisce 1 due volte e dopo che None) . Dovrei scavare in questa direzione? Voglio dire, dovrei capire il concetto di questi set per trovare una soluzione al mio problema?

risposta

9

DB-API cerca di gestire le transazioni per conto proprio, di iniziare una transazione sul primo comando e con la propria chiamata API per commetterlo, quindi:

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() 

A mio parere, questa è una grave, errore di progettazione abbagliante dell'API DB di Python, che lo rende un serio problema per eseguire comandi al di fuori delle transazioni e per avere un controllo adeguato sulle transazioni, ad es. usare cose come lo BEGIN EXCLUSIVE TRANSACTION di SQLite. È come se a qualcuno senza esperienza di database reale fosse consentito progettare l'API ...

+6

+1, oppure puoi semplicemente impostare __autocommit__ su true in primo luogo, che è disabilitato per impostazione predefinita; come questo 'cursor.connection.autocommit (True)',. – mouad

+0

@singularity: ma se lo fai, stai modificando il comportamento dell'API a un livello basso, che può morderti se stai trasmettendo la connessione al codice di terze parti, ad esempio. –

+0

@Glenn Maynard: no non lo è, abiliterà solo l'opzione __autocommit__ per la connessione del cursore che abbiamo creato nel nostro codice :), abilitare l'autocommit può essere molto utile in alcuni casi, quando vogliamo risparmiare tempo reale invece di fare ogni volta 'cursor.commit()' ... – mouad

Problemi correlati