You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在CodeIgniter 4中处理MySQL死锁问题的技术求助

解决CodeIgniter中MySQL死锁捕获与重试问题

你的问题核心在于CodeIgniter默认不会将数据库错误抛出为可捕获的Exception,所以普通的try-catch(\Exception $e)无法抓到死锁错误。下面是具体的解决步骤:

1. 开启数据库异常模式

在CodeIgniter中,需要先配置数据库连接,让它把错误以异常形式抛出。可以选择全局配置或方法内临时配置:

全局配置(database.php)

找到你的数据库配置数组,添加或修改errorMode参数(适用于CodeIgniter 4):

public $default = [
    'DSN'      => '',
    'hostname' => 'localhost',
    'username' => 'root',
    'password' => '',
    'database' => 'your_db',
    'DBDriver' => 'MySQLi',
    'DBPrefix' => '',
    'pConnect' => false,
    'DBDebug'  => false, // 关闭默认调试输出
    'charset'  => 'utf8',
    'DBCollat' => 'utf8_general_ci',
    'swapPre'  => '',
    'encrypt'  => false,
    'compress' => false,
    'strictOn' => false,
    'failover' => [],
    'port'     => 3306,
    'errorMode' => \CodeIgniter\Database\BaseConnection::ERRORMODE_EXCEPTION, // 关键配置
];

方法内临时设置

如果不想全局开启异常模式,可以在updateUserBalance方法内临时设置:

$this->db->errorMode(\CodeIgniter\Database\BaseConnection::ERRORMODE_EXCEPTION);

2. 捕获数据库异常并实现死锁重试

MySQL死锁的错误码是1213,捕获到数据库异常后,通过错误码判断是否为死锁,再实现重试逻辑(示例设置最多3次重试):

public function updateUserBalance($userid, $balance, $retryCount = 3)
{
    try {
        // 临时开启异常模式(若全局未配置)
        $this->db->errorMode(\CodeIgniter\Database\BaseConnection::ERRORMODE_EXCEPTION);
        
        return $this->db->table($this->user)
            ->set('balance', "balance+{$balance}", false)
            ->where('id', $userid)
            ->update();
    } catch (\CodeIgniter\Database\Exceptions\DatabaseException $e) {
        // 判断是否为死锁错误
        if ($e->getCode() == 1213 && $retryCount > 0) {
            log_message('error', "Deadlock occurred, retrying... (remaining attempts: {$retryCount-1})");
            // 递归重试,每次重试次数减1
            return $this->updateUserBalance($userid, $balance, $retryCount - 1);
        }
        
        // 非死锁错误或重试耗尽,记录错误并返回
        log_message('error', 'Database error: ' . $e->getMessage() . ' (code: ' . $e->getCode() . ')');
        return false;
    }
}

3. CodeIgniter 3兼容方案

如果你使用CodeIgniter 3,配置和捕获逻辑略有不同:

public function updateUserBalance($userid, $balance, $retryCount = 3)
{
    $this->db->db_debug = false; // 关闭默认调试输出
    try {
        $result = $this->db->table($this->user)
            ->set('balance', "balance+{$balance}", false)
            ->where('id', $userid)
            ->update();
            
        if (!$result) {
            $error = $this->db->error();
            throw new \Exception($error['message'], $error['code']);
        }
        return $result;
    } catch (\Exception $e) {
        if ($e->getCode() == 1213 && $retryCount > 0) {
            log_message('error', "Deadlock occurred, retrying... (remaining attempts: {$retryCount-1})");
            return $this->updateUserBalance($userid, $balance, $retryCount - 1);
        }
        
        log_message('error', 'Database error: ' . $e->getMessage() . ' (code: ' . $e->getCode() . ')');
        return false;
    }
}

内容的提问来源于stack exchange,提问作者evan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 22:16:22