国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

MySQL更新數(shù)據(jù)時會報錯,SQLSTATE[HY000]: General error: 1243 Unknown prepared statement handler (23039) given to mysqld_stmt_execute

Forsend

代碼大概是這樣的

    private function getDb()
    {
        return new \Workerman\MySQL\Connection('DB_HOST', 'DB_PORT', 'DB_USER', 'DB_PWD', 'DB_NAME');
    }

    public function func($id)
    {
        $db = $this->getDb();
        try {
            // 一些業(yè)務

            // 更新操作
            $db->query("UPDATE `table_name` SET field1 = 1 WHERE `id` = {$id}");

            // result通過業(yè)務拿到
            if ($result) {
                $db->query("UPDATE `table_name` SET field2 = 2 WHERE `id` = {$id}");
            }
        } catch (\Exception $exception) {
            echo $exception->getMessage();
        }
    }

第一個更新語句沒問題,如果result為true,執(zhí)行第二個更新時,會拋出異常,報錯信息是

UPDATE `table_name` SET `field2` = 2 WHERE `id` = 12345678 
SQLSTATE[HY000]: General error: 1243 Unknown prepared statement handler (23039) given to mysqld_stmt_execute


不是必定觸發(fā),但是概率不小
然后我在網(wǎng)上搜了下報錯信息,tp框架有類似的問題,解決辦法是把PDO的PDO::ATTR_EMULATE_PREPARES屬性改成true
按照這樣把workerman源碼改下也正常了,但具體原因不清楚

截圖

PHP 7.2
mysql 5.7 有讀寫分離

3916 1 0
1個回答

MarkGo

我覺得可能是斷線重連時產(chǎn)生的問題。
prepared statement handler 這個是通過mysql預處理進行查詢;
類似一個查詢執(zhí)行2次命令,
第一次執(zhí)行:
PREPARE STMT FROM 'SELECT * FROM table LIMIT ?';
第二次執(zhí)行:
SET @a=1;EXECUTE STMT USING @a;

當?shù)谝淮螆?zhí)行后發(fā)生斷線重連時,運行的第二段sql則會報錯,因為對應的預處理已經(jīng)不存在了。

而設置PDO::ATTR_EMULATE_PREPARES = true,
則代表不使用mysql的預處理,通過PDO模擬預處理情況,最終只執(zhí)行一次。

如果要印證猜測是否成立,可以看看mysql的errlog

  • Forsend 2022-07-27

    感謝解答。請問會不會跟MySQL讀寫分離有關,網(wǎng)上搜這個報錯信息時,找到一些tp框架也會報這個錯,都是開啟了讀寫分離。我這邊也用了讀寫分離中間件

  • MarkGo 2022-07-28

    這個應該不會吧,具體可能也要看中間件的處理方式,
    出現(xiàn)這個錯誤代表著預處理時模板語句沒執(zhí)行,但卻執(zhí)行了參數(shù)綁定導致出錯。
    我也是用讀寫分離,但是我是代碼級的,利用mariadb特性進行的,
    如一些耗時且沒太高實時性要求的,就在sql前加入/SLAVE/select xxxxx
    并未出現(xiàn)過這些錯誤。

年代過于久遠,無法發(fā)表回答
??