2016-08-28 40 views
0

我正在努力提高Web應用程序的數據導入性能,並且大幅度提高了性能的一件事是將數據庫相關邏輯從服務器端代碼移植到存儲中程序和功能在數據庫中。在單個語句中多次調用存儲過程的錯誤1064

此外,當處理大量類似的查詢時,將它們批量排隊以稍後在單個SQL事務中執行,從而顯着減少導入過程的瓶頸。


不幸的是我來沿途有問題,因爲某些原因,我不能調用存儲過程不止一次在一個SQL命令。

拿這個SQL我連續兩次調用LegacyUpdateProduct來展示我的問題。

SQL

的存儲過程接受與數據的幾個參數,不返回結果集,進出給人行ID,在這種情況下,我們沒有必要反正@ID變量。

CALL LegacyUpdateProduct(92,'00010','ADAISD 345',18.81,'91020200','FSB92','GS8219','FSB92',TRUE,2,3,0,0,@ID);CALL LegacyUpdateProduct(277,'0002335600','TPASD 987',6.04,'0 002 335 ','UX79','','',TRUE,2,3,0,0,@ID); 

PHP

在PHP的人會期望簡單地運行與兩個電話查詢,以LegacyUpdateProduct和一切都會好起來的。

$sql = "CALL LegacyUpdateProduct(92,'00010','ADAISD 345',18.81,'91020200','FSB92','GS8219','FSB92',TRUE,2,3,0,0,@ID);CALL LegacyUpdateProduct(277,'0002335600','TPASD 987',6.04,'0 002 335 ','UX79','','',TRUE,2,3,0,0,@ID);" 
# With Code Igniter 
$this->db->query($sql); 
# Or with raw PHP 
mysqli_query($this->db->conn_id, $sql); 

不幸的是,情況並非如此。使用Code Igniter或普通PHP運行此查詢會引發SQL錯誤。

說明:我仔細檢查了數據,並使用Code Igniter DB轉義機制來產生更安全的查詢。

錯誤號1064,您在您的SQL語法錯誤

最有意思的是,當我複製並粘貼在phpMyAdmin或MySQL Workbench中的所謂錯誤SQL,它運行平穩,沒有錯誤或警告。

事實上,我能夠在單個查詢中連續運行多達50個連續的LegacyUpdateProduct調用,而PHPMyAdmin和MySQL Workbench沒有問題。

我已經通過Google和SO查看了一些可能相關或有幫助的問題,但還沒有發現太多的東西,除非這可能是某種類型的Code Igniter錯誤,但即使使用純PHP我發現了同樣的問題。

在對另一個SO question有一些相關的答案中,它提到這可能是一個Code Igniter錯誤,但它不能解釋爲什麼用普通的PHP mysqli_query()這個查詢失敗。

在另一個question的註釋中,對於不同的錯誤,提示可能存在併發問題,如果不等待前面的完成,就無法順序調用該過程。我沒有足夠的理解MySQL的併發來進行聲明,但是,不應該在查詢之後執行每個命令。

幫助?

+1

如果您想一次運行2條語句,則必須使用[multi_query](http://php.net/manual/de/mysqli.quickstart.multiple-statement.php)。或者只是將查詢拆分爲兩個查詢。 'query'不知道如何在第一個';'之後使用代碼,這就是爲什麼你會得到語法錯誤的原因。 – Solarflare

+0

有趣的是,被用來在同一個sql語句中運行多個查詢,從來沒有考慮過'mysqli'可能已經實現了該操作方法來安全防範惡意的意圖。 我已經探索過這個途徑,並且我能夠在第一次調用'multi_query'的同一語句中運行所有存儲過程,但是下面的調用'multi_query'正在下降。 但更重要的是,我並沒有注意到性能提升,我會閱讀文檔並更好地瞭解這種方法,更重要的是找到MySQL連接標誌可以在';'之後執行查詢。 –

+1

爲了節省您的時間,唯一能夠在';'正在使用'_multi'後執行的東西。而且你不會得到很多性能提升(只要你保持連接打開狀態)。總是喜歡單個querys!有很多原因!例如。 ('_multi'需要你在繼續之前讀取所有結果,這就是爲什麼你的後續查詢失敗)......對於一些技術見解(例如連接設置),看看[C API支持多個語句執行](https://dev.mysql.com/doc/refman/5.7/en/c-api-multiple-queries.html) – Solarflare

回答

0

在PHP的人會期望簡單地用兩個電話

運行查詢,有像「查詢有兩個叫」沒有這樣的事。你實際有什麼是兩個SQL查詢。雖然mysqli :: query每次調用只能運行一個SQL查詢。

當處理大量類似的查詢時,將它們批量排隊以便稍後在單個SQL命令中執行,從而顯着減少導入過程的瓶頸。

最有可能的是它的famous innodb's paranoid mode。請將其關閉或在交易中包裝更新。你將看到單獨的query()調用沒有明顯的減少。

+0

道歉,我錯誤地使用了SQL命令而不是SQL問題中的事務,第二次在您的答案中引用。每批查詢都在單個事務中處理,我將啓動事務,調用每個查詢並提交事務。 –

+0

在存儲過程中包裝我的調用是一個很好的建議。起初,運行存儲過程的所有58k調用需要211分鐘,平均每次調用0.22秒。當我嘗試以每批1k的批次運行它們時,總運行時間僅爲56分鐘,平均爲0.06秒。 –

+0

你的提示再次相當有用。我對你的建議採取的第一種方法還不夠好,對改進感到不滿意,回到製圖板並重新設計了進口部分。長話短說,現在下降到大約270秒。 –

相關問題