我有一個具有1.7M記錄表的Mysql系統。這是一個生產系統。它以前是Myisam &非常有彈性,但作爲一個測試,我已經將它轉換爲Innodb(和php腳本),希望它運行得更快,行級鎖定會使它更具彈性。它由30個使用PHP 7 CLI的機器人提供服務。他們每個人都會掃描表中是否需要更新的記錄,然後更新它們,然後繼續作爲團隊的一部分,直到完成任務。他們以40行爲單位執行此操作,這意味着劇本運行約42,500次。Mysql Innodb可以處理重度並行處理
但在測試過程中,我注意到Innodb事務的一些特性,我沒有想到,似乎是showstoppers。在我回滾之前,我想我會問別人的觀點,我是否完全有錯誤或者證明或反駁我的發現。圍繞一個DB調用(所有搜索字段建立索引)跌破發行中心是僞代碼:
update table set busy=$token where condition=true order by id $order limit $units
if affected rows != $units
do function to clear
return
else do stuff.....
endif
前 在MyISAM的結果是,每個機器人需要一個運行在獲得表級鎖,只是排隊,直到他們得到他們。這可能會產生瓶頸,但所有問題都可以在一分鐘內解決。
AFTER 在Innodb下,對於一個機器人來說這個調用是可以的,但是對多用戶工作的任何嘗試都會導致'鎖定超時超時;嘗試重新啓動交易「。 更改wait_timeout/autocommit/tx_isolation沒有區別。也不轉換這一個交易和使用:
begin
select .... for update
update
test
commit or rollback
在我看來是:
1 Innodb的產生,即使您沒有設置交易的所有更新的隱式交易。如果這些時間太長,那麼並行處理是不可能的。
2更重要的是,當Innodb鎖定行時,它並不知道它鎖定了哪些行。你可以這樣做:
begin
select 10 rows where condition=this for update
update the rows I locked
commit
你必須做兩個相同的調用是這樣的:
begin
select 10 rows where condition=this for update
update 10 rows where condition=this
commit
這是死鎖的robot1配方可以鎖定40行,robot2鎖40種人等但隨後robot1更新了40行,這可能與它剛剛鎖定的行完全不同。這將繼續,直到所有行都被鎖定,並且它們不能回寫到表中。
所以,當我有30個機器人爭奪需要更新的行時,我覺得Innodb對我而言是無用的。這是聰明的,但不夠聰明,以處理重型並行處理。
有什麼想法?
「當Innodb鎖定行時,它不知道'它鎖定了哪些行',只有當你沒有一個好的索引時纔是真的。它鎖定執行查詢時需要查看的所有行(可能還有間隙)。檢查執行計劃,例如一個文件夾,一個全表掃描或類似的東西(和/或將其添加到除了索引和您認爲合適的查詢之外的問題)。檢查你是否啓用了自動提交模式,它在每個語句之後提交。它會像'update .... commit ... test ... commit'那樣工作,不像'update ... test ... commit'那樣在僞代碼中。 (但MyISAM也是如此)。 – Solarflare
再次開始測試,並在超時前運行「顯示引擎innodb狀態」。這會給你很多關於當前正在發生的事情的信息。 –
「運行約42,500次」 - 每次?每兩週? –