2016-07-14 15 views
8

SQLAlchemy Verwendung einer MySQL-Datenbank abzufragen ich die folgende Störung erhalte:ignorieren Sperren in MySQL-Datenbank in sqlalchemy Abfrage

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

Zuerst gehe ich davon aus, dass die Fehlermeldung Kommentar zu „betrachten einen session.no_autoflush Block mit Wenn dieser Flush zu früh auftritt, "ist die andere Sitzung die Sperre, nicht die Sitzung, die ich für meine aktuelle Abfrage verwende? Wenn ich diesen Rat befolgen würde, würde dies helfen, Sperren auf der Datenbank im Allgemeinen zu vermeiden? Zweitens muss ich nur lesen und muss keine Änderungen an den Abfrageergebnissen schreiben. Daher würde ich gerne wissen, wie man die Sperre ignoriert und nur liest, was gerade in der Datenbank ist. Ich glaube, das SQL ist NOWAIT, aber ich sehe nicht, wie man das in der sqlalchemy API tut.

+0

Bitte geben Sie die SQL-Anweisungen an (bei beiden Verbindungen) und 'SHOW CREATE TABLE' und' SHOW ENGINE = InnoDB STATUS; '(wenn möglich, wenn das Problem auftritt). Von dem, was Sie angegeben haben, können wir nicht sagen, warum es gesperrt ist, noch viele andere wichtige Details. –

+0

Geben Sie auch Informationen zu "no_autoflush" von sqlalchemy an. Wir müssen herausfinden, was MySQL unter den Deckeln konstruiert. –

+0

@RickJames keine SQL-Konstrukte unterly [autoflush] (http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.params.autoflush). Es ist nur wie SQLAlchemy-Sitzung den Status behandelt. Wenn die Sitzung ausstehende Änderungen hat, die noch nicht in die DB geleert wurden (Einfügungen, Aktualisierungen, Löschungen), werden diese vor dem Ausführen der nächsten Abfrage an die Datenbank geleert, wenn autoflush verwendet wird. Kann OP nicht ohne eine mcve helfen, etwas sperrt etwas und ein Flush wird ausgegeben, bevor irgendeine Abfrage etwas gesperrt verwendet ... –

Antwort

1

Angenommen, Sie verwenden die mysql.connector, ist der Standardwert der autocommit-Eigenschaft False, was dazu führen kann, dass Ihr Skript aufgrund einer anderen Sitzung, die auf den Abschluss wartet, hängen bleibt.

SQLAlchemy wird mit dem BEGIN statements, (alias von START TRANSACTION), der die Sitzung verursachen LOCK der Tabelle/Datenbank zu erwerben, und Ihre Verbindung wird warten, bis die Sperre wird genehmigt bekommen.

dieses Verhalten zu überwinden (und aufgrund der Tatsache, dass Sie sagen, Sie müssen nur die Daten während der Sitzung READ) Sie autocommit = True gesetzt, wenn Ihre Session zu erstellen:

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

Eine weitere Option - nachdem Sie erstellen Sie die Sitzung, die Sie SET AUTOCOMMIT=1 ausführen:

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 schätzen Sie eine Erklärung für jede Down-Abstimmung – Dekel

+1

Eines der ersten Dinge erwähnt [in der Sqla-Dokumentation] (http: // docs.sqlalchemy.org/en/latest/orm/session_transaction.html#autocommit-mode) ist: "** Warnung **" Autocommit "Modus sollte ** nicht für den allgemeinen Gebrauch berücksichtigt werden **." –

+0

@ IljaEverilä, autocommit = True ist wirklich keine gute Praxis, deshalb ist es in der Dokumentation so erwähnt, aber wenn es keinen Transaktionscode (zum Beispiel schreibgeschütztes Skript) gibt, wird es viel billiger für den Server, diese Transaktion mit Autocommit = True zu haben. Die Tatsache, dass SQLAlchemy autocommit = False für jede Sitzung hat, ist nicht immer so eine gute Übung. Außerdem - Wenn Sie die MyISAM-Engine verwenden, macht es keinen Sinn, eine Transaktion zu haben, und dort ist es sogar noch besser, autocommit = True zu haben. – Dekel