2016-07-14 43 views
8

使用SQLAlchemy的查詢MySQL數據庫,我收到以下錯誤:忽略鎖定在MySQL數據庫中的SQLAlchemy查詢

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

首先,我認爲錯誤消息的評論「考慮使用session.no_autoflush塊如果此刷新過早發生「是關於放置鎖的其他會話,而不是我用於當前查詢的會話?如果我遵循這個建議,這將有助於避免在數據庫上鎖定一般?其次,我只需要閱讀並不需要對查詢結果進行修改,所以我想知道如何忽略鎖並只讀數據庫中的當前內容。我相信SQL是NOWAIT,但我沒有看到在sqlalchemy API中如何做到這一點。

+0

請提供所涉及的SQL語句(在兩個連接上),以及'SHOW CREATE TABLE'和'SHOW ENGINE = InnoDB STATUS;'(如果可能,當問題發生時)。從你提供的內容來看,我們不能說出它爲什麼鎖定,還有很多其他重要細節。 –

+0

也提供有關sqlalchemy的「no_autoflush」的信息;我們需要弄清楚什麼是MySQL構造。 –

+0

@RickJames沒有SQL構造underly [autoflush](http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.params.autoflush)。這正是SQLAlchemy會話處理狀態的方式。如果會話有未掛起的更改尚未刷新到數據庫(插入,更新,刪除),則會在運行下一個查詢(如果使用autoflush)之前將其刷新到數據庫。但是,如果沒有mcve,不能幫助OP,在某些查詢正在使用鎖定的某些內容之前,某事正在鎖定某些內容併發出刷新... –

回答

1

假設您使用的是mysql.connectorautocommit屬性的默認值爲False,這可能會導致腳本因其他正在等待完成的會話而掛起。

SQLAlchemy使用BEGIN statements,(的START TRANSACTION化名)造成採集表/數據庫鎖定會話,並且您的連接將等到鎖將得到批准。

爲了克服這個問題(並且由於事實,你說你只需要在會議期間讀取數據),您可以設置自動提交=真正的創建Session時:

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

另一種選擇 - 在你創建您可以執行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

將欣賞任何解釋任何投票 – Dekel

+1

提到的第一件事[在sqla文檔](http:// docs。sqlalchemy.org/en/latest/orm/session_transaction.html#autocommit-mode)是:「**警告**」自動提交「模式不應被視爲通用**。」 –

+0

@IljaEverilä,autocommit = True實際上並不是一個好習慣,這就是爲什麼它在文檔中被這樣提及的原因,但是,如果不需要事務代碼(例如只讀腳本),它將會很多服務器使用autocommit = True進行交易更便宜。 SQLAlchemy對每個會話都有autocommit = False的事實並不總是這樣的一個好習慣。而且 - 如果你使用的是MyISAM引擎,那麼交易就沒有意義了,那麼autocommit = True就更好了。 – Dekel