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è)務(wù)
// 更新操作
$db->query("UPDATE `table_name` SET field1 = 1 WHERE `id` = {$id}");
// result通過(guò)業(yè)務(wù)拿到
if ($result) {
$db->query("UPDATE `table_name` SET field2 = 2 WHERE `id` = {$id}");
}
} catch (\Exception $exception) {
echo $exception->getMessage();
}
}
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)上搜了下報(bào)錯(cuò)信息,tp框架有類(lèi)似的問(wèn)題,解決辦法是把PDO的PDO::ATTR_EMULATE_PREPARES屬性改成true
按照這樣把workerman源碼改下也正常了,但具體原因不清楚
PHP 7.2
mysql 5.7 有讀寫(xiě)分離
我覺(jué)得可能是斷線重連時(shí)產(chǎn)生的問(wèn)題。
prepared statement handler 這個(gè)是通過(guò)mysql預(yù)處理進(jìn)行查詢;
類(lèi)似一個(gè)查詢執(zhí)行2次命令,
第一次執(zhí)行:
PREPARE STMT FROM 'SELECT * FROM table LIMIT ?';
第二次執(zhí)行:
SET @a=1;EXECUTE STMT USING @a;
當(dāng)?shù)谝淮螆?zhí)行后發(fā)生斷線重連時(shí),運(yùn)行的第二段sql則會(huì)報(bào)錯(cuò),因?yàn)閷?duì)應(yīng)的預(yù)處理已經(jīng)不存在了。
而設(shè)置PDO::ATTR_EMULATE_PREPARES = true,
則代表不使用mysql的預(yù)處理,通過(guò)PDO模擬預(yù)處理情況,最終只執(zhí)行一次。
如果要印證猜測(cè)是否成立,可以看看mysql的errlog
感謝解答。請(qǐng)問(wèn)會(huì)不會(huì)跟MySQL讀寫(xiě)分離有關(guān),網(wǎng)上搜這個(gè)報(bào)錯(cuò)信息時(shí),找到一些tp框架也會(huì)報(bào)這個(gè)錯(cuò),都是開(kāi)啟了讀寫(xiě)分離。我這邊也用了讀寫(xiě)分離中間件
這個(gè)應(yīng)該不會(huì)吧,具體可能也要看中間件的處理方式,
出現(xiàn)這個(gè)錯(cuò)誤代表著預(yù)處理時(shí)模板語(yǔ)句沒(méi)執(zhí)行,但卻執(zhí)行了參數(shù)綁定導(dǎo)致出錯(cuò)。
我也是用讀寫(xiě)分離,但是我是代碼級(jí)的,利用mariadb特性進(jìn)行的,
如一些耗時(shí)且沒(méi)太高實(shí)時(shí)性要求的,就在sql前加入/SLAVE/select xxxxx
并未出現(xiàn)過(guò)這些錯(cuò)誤。