2016-07-14 136 views
8

Utilizzando SQLAlchemy per interrogare un database MySQL Sto ottenendo il seguente errore:Ignora blocco in MySQL database in SQLAlchemy Query

sqlalchemy.exc.OperationalError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely) (_mysql_exceptions.OperationalError) (1205, 'Lock wait timeout exceeded; try restarting transaction')

In primo luogo, presumo che il commento messaggio di errore per "considerare l'utilizzo di un blocco session.no_autoflush se questo svuotamento si verifica prematuramente "riguarda l'altra sessione che blocca il blocco, non la sessione che sto utilizzando per la mia query corrente? Se ho seguito questo consiglio, questo aiuta a evitare i blocchi sul database in generale? In secondo luogo, ho solo bisogno di leggere e non ho bisogno di scrivere modifiche ai risultati della query, quindi vorrei sapere come ignorare il blocco e solo leggere ciò che è attualmente nel database. Credo che lo sql sia NOWAIT, ma non vedo come farlo nell'API sqlalchemy.

+0

Fornire le istruzioni SQL coinvolte (su entrambe le connessioni) e 'SHOW CREATE TABLE' e' SHOW ENGINE = InnoDB STATUS; '(se possibile, quando si verifica il problema). Da quello che hai fornito, non possiamo dire perché è bloccato, né molti altri dettagli importanti. –

+0

Fornire anche informazioni su "no_autoflush" di sqlalchemy; abbiamo bisogno di capire quale sia la costruzione di MySQL sotto le coperte. –

+0

@RickJames no costrutti SQL sottostanti [autoflush] (http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.params.autoflush). È proprio come lo stato di SQLalchemy gestisce lo stato. Se la sessione ha modifiche in sospeso non ancora scaricate su DB (inserimenti, aggiornamenti, eliminazioni), queste verranno scaricate nel DB prima dell'esecuzione della query successiva, se è in uso l'autoflush. Tuttavia, non posso aiutare OP senza un mcve, qualcosa sta bloccando qualcosa e un flush emesso prima che alcune query stiano usando qualcosa bloccato ... –

risposta

1

Supponendo che si stia utilizzando il mysql.connector, il valore predefinito della proprietà autocommit è False, che potrebbe causare il blocco dello script a causa di un'altra sessione in attesa di completamento.

SQLAlchemy sta usando il BEGIN statements, (alias START TRANSACTION) che causano la sessione di acquisire BLOCCO del tavolo/database e la tua connessione attenderà sarà ottenere approvato la serratura.

Per ovviare a questo comportamento (e per il fatto che lei ha detto che solo bisogno di leggere i dati durante la sessione) è possibile impostare autocommit = True quando si crea la sessione:

Session = sessionmaker(bind=engine, autocommit=True) 

Un'altra opzione - dopo aver creare la sessione è possibile eseguire SET AUTOCOMMIT=1:

s = Session() 
s.execute("SET AUTOCOMMIT=0") 

You can also try to set the autocommit property directly in the connection string:

engine = create_engine("mysql+mysqlconnector://user:[email protected]/dbname?autocommit=1") 

However I didn't test it. According to the documentations it should work.

+0

Will apprezzare una spiegazione per qualsiasi voto negativo – Dekel

+1

Una delle prime cose citate [nella documentazione di sqla] (http: // docs.sqlalchemy.org/en/latest/orm/session_transaction.html#autocommit-mode) è: la modalità "** Warning **" autocommit "dovrebbe ** non essere considerata per uso generale **." –

+0

@ IljaEverilä, autocommit = True NON è davvero una buona pratica, questo è il motivo per cui è menzionato in questo modo nella documentazione, tuttavia, se non c'è bisogno di un codice transazionale (script di sola lettura, per esempio) sarà molto meno costoso perché il server abbia quella transazione con autocommit = True. Il fatto che SQLAlchemy abbia autocommit = False per ogni sessione non è sempre una buona pratica. Inoltre, se si sta utilizzando il motore MyISAM, non ha senso avere transazioni e lì è ancora meglio avere autocommit = True. – Dekel