報錯內容如下:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 5
內容概要
作為一名運維小哥,先后經歷了沒有DBA的技術團隊,有DBA的技術團隊,然后又回到了沒有DBA的技術團隊。當開發人員提交SQL執行需求,運維人員進行SQL執行后,出現SQL報錯。根據簡單的報錯信息大概能定位到時SQL語法的不嚴謹或者語法性問題,但單從sql層面上來講,作為一個沒有DBA的技術團隊,經常使用SQL的也就是開發人員,運維人員更多時候是一個sql執行的角色,所以作為運維的我,因為不是專業的DBA,不能明確的指出開發人員SQL的缺陷。
所以,當SQL執行出現問題,就變得有點意思了~
下面,請允許我還原下開車現場:
說明:
企業所使用的服務器環境及服務等運維人員並沒有全權掌控,確實存在不足。一部分是歷史遺留原因;一部分是企業團隊環境(企業在北京、上海、南京等多地設有子公司,致使有些東西難以做到全權統籌);同時作為運維小弟呢,光有一腔抱負,但卻沒有指點江山的職權,所以呢,有些事務確實難以推動。
我呢,也只能在其位,謀其職,做好分內之事,同時,有時也會厚着臉皮跟老大說一些自己對於某些運維事務的處理方式、處理思路及運維環境等見解。至於是不是白說,我自己也不是很清楚^_^
運維流程、運維事務處理方式的變更中的某些事務確實是牽一發而動全身,要改革,首先要自己能厚着臉皮說思想,其次要老大能心寬點頭,接着要進行事務的推動(內容包括 運維與開發的對接信息內容、運維流程、事務處理手段等等),當中不僅需要堅定的勞苦付出,也存在着責任,存在着風險,即使說我來扛責任,但事實是我只是個微不足道的小角色,最終的擔子會壓在leader身上。不動沒風險,只是機械勞作多點而已;而動了呢,動好了,在外行人眼里可能看不出來運維團隊做的優化及其收益,提高了些許的工作效率,有些人也會覺得是理所應當。而動壞了,那就麻煩大了。所以當中的利弊,當中的難易,並非三言兩語能說道明白。
所以呢,目前還是墨守成規的進行着運維操作~~
報錯:
環境:
a)運維團隊及Leader在北京,我在上海負責相關上海的運維事務;
b)測試環境MySQL全權開發掌管及自用,生產環境運維管理。
角色:
Me(運維,just me) Dev(開發) Cap(運維leader,我老大)
對白:
Me:Hi,你這SQL執行報錯,語句有問題吧?
Dev:沒有問題啊,我在測試環境執行都能成功的。
Me:但這確實是報錯了啊,報錯截圖我給你了。
此刻空氣凝固了10s左右 ~~~
Me:你這測試環境是怎么執行的?
Dev:用IDE工具。
Me:工具執行跟登陸數據庫執行命令應該沒區別吧,你這MySQL什么版本?
Dev:5.6
Me:生產環境是5.7,你確定不是版本差異導致的語法不兼容?
Dev:SQL沒問題的,我本機的MySQL5.7執行都沒問題。
Me:呃。。。那之前生產創建觸發器出現這種情況咋處理的?
Dev:是Cap開啟了數據庫的某個全局權限,命令行執行SQL還是不行,但是我用IDE工具就成功了,所以之前是Cap開啟全局權限,我這里執行。
Me:呃。。。那我問問。
Me:@Cap 老大,開發創建觸發器的需求,需要開全局配置,之前我反映過開了那個可能會造成主從同步異常,所以上次你跟我說別隨便開,那這次的需求咋處理?
Cap:先別開,你網上查查資料,處理下。
Me:好的,我琢磨下。。。
此刻我的內心讀白:
開發說SQL沒問題,但是生產環境執行確實報錯了,報錯提示說的是版本差異或者SQL語法的問題,我覺得Dev在胡亂開車,奈何的是我卻沒有證據(因為自身SQL水平有限)~~
好吧,硬着頭皮找問題吧。
問題解決
筆者通過問題排錯,資料查詢,並將數據導入到測試環境的MySQL5.7版本,然后進行相關的觸發器創建SQL執行測試並多次修改試驗,最后成功捕獲問題並解決。
以下是兩種不同解決方案,前者是之前老大的修改全局配置權限的操作方式,后者是筆者的解決方式:
錯誤解決姿勢
# 開啟MySQL的某項權限
mysql > set global log_bin_trust_function_creators=1;
# 權限開啟后並給對應庫的操作權限賬號,由開發通過IDE工具執行SQL,操作成功!
# log_bin_trust_function_creators 參數說明:
當二進制日志啟用后,這個變量就會啟用。它控制是否可以信任存儲函數創建者,不會創建寫入二進制日志引起不安全事件的存儲函數。如果設置為0(默認值),用戶不得創建或修改存儲函數,除非它們具有除CREATE ROUTINE或ALTER ROUTINE特權之外的SUPER權限。 設置為0還強制使用DETERMINISTIC特性或READS SQL DATA或NO SQL特性聲明函數的限制。 如果變量設置為1,MySQL不會對創建存儲函數實施這些限制。此變量也適用於觸發器的創建。
說明:
那么為什么MySQL有這樣的限制呢? 因為二進制日志的一個重要功能是用於主從復制,而存儲函數有可能導致主從的數據不一致。同時經過實操后也確實出現了主從同步數據異常情況,所以,切勿輕易修改 log_bin_trust_function_creators 參數的默認值!
正確解決姿勢
# 修改MySQL命令執行默認分隔符
說明:
a)圖中三部分紅框內容為筆者添加;
b)第一框是修改數據庫默認的分隔符,指定為 " // " ;
c)第二框是結束整條sql內容;
d)第三框是將分隔符改回到默認;
e)因sql語句中存在分號 ";" ,其用於整條sql內部的小斷句,而MySQL默認的命令分隔符也是分號,故容易出現符號混淆,導致SQL執行異常。所以改變默認的命令行的分隔符用以區別分號,便能完美解決問題。