Golang 用go-sql-driver 調用MySQL存儲過程時的問題排查


今天在用go-sql-driver做MySQL driver調用MySQL的存儲過程時遇到一個罕見的報錯。本文對這個錯誤及其解做一個簡單的總結。

1 問題描述

按照go中sql包提供的接口,應用層代碼調用MySQL存儲過程的代碼一般如下所示:

       result, err := dbh.Exec("call some_procedure(?, ?)", param1, param2)
        if err != nil {
                // error handler
        }

       // using result...

  但是在實際執行的時候err不為nil,err的值是MySQL返回給driver的出錯信息:

Error 1312: PROCEDURE tcheck_db.update_vs_available can't return a result set in the given context

2  問題原因

出現這個問題的原因是在調用存儲過程時,MySQL希望客戶端的連接類型是multi-statement模式,但是go-sql-driver這個包目前沒有設置這個連接模式,所以MySQL給返回了1中的錯誤。

實際上,在用go-sql-driver時,除了無法調用存儲過程外,還存在一些其他的限制,這些限制可以在go-database-sql-surprises中看到。

go-sql-driver的討論區也有人報出了這個問題,見這里

3 問題解法

既然找到了病因,那就要對症下葯,能想到的辦法就是將go-sql-driver連接MySQL時的connection mode設置為multi-statement。方法是:

1) go get github.com/go-sql-driver/mysql 下載依賴包

2)編輯文件src/github.com/go-sql-driver/mysql/packets.go文件,在函數writeAuthPacket(cipher []byte) (大約在210行)的客戶端標志位處添加下面兩個標志:

 clientMultiStatements 和 clientMultiResults

添加后的代碼如下:

func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
        // Adjust client flags based on server support                                                                                     
        clientFlags := clientProtocol41 |
                clientSecureConn |
                clientLongPassword |
                clientTransactions |
                clientLocalFiles |
                clientMultiStatements |    // 添加這行
                clientMultiResults |       //再添加這行
                mc.flags&clientLongFlag

        if mc.cfg.clientFoundRows {
                clientFlags |= clientFoundRows
        }

        ...

3,rebuild您的依賴go-sql-driver的代碼。

 

OK。經過上面三步修改之后,執行1中的存儲過程代碼時,就不會報錯了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM