mysql排它锁碰到的问题

问题描述

通过定时任务发送微信消息推送,每分钟执行一次php脚本
为了避免重复发送,加入了排它锁,发现添加的索引未生效,mysql返回报错,期间新的数据插入也未成功

添加的索引未生效,是否导致行锁升级为了表锁?
图片描述

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

public function send_test()
{
    M()->startTrans();
    try{
        $sql = "select * from wh_wechat_notification where status = 0 for update";
        $wechat_info = M()->query($sql);
        foreach ($wechat_info as $key => $val) {
            $fp = fsockopen('api.weixin.qq.com', 80, $error, $errorstr, 1);
            $http = "POST /cgi-bin/message/template/send?access_token={$this->access_token} HTTP/1.1\r\nHost: api.weixin.qq.com\r\nContent-type: application/x-www-form-urlencoded\r\nContent-Length: " . strlen($val['data']) . "\r\nConnection:close\r\n\r\n{$val['data']}\r\n\r\n";
            fwrite($fp, $http);
            while (!feof($fp))
            {
                $content = fgets($fp);
            }
            fclose($fp);
            $res = json_decode($content,true);
            if($res['errcode'] == 0 || $res['errcode'] == 43004) {
                $save['status'] =1;
                $save['send_at'] =date('Y-m-d H:i:s');
                M('wechat_notification')->where("id ={$val['id']}")->save($save);
            }else{
                F('wx_token',['value' => null,'time' => time() - 1]);
                \Think\Log::write("模板消息推送失败,返回结果:\r\n".implode(',',$res) ,'WARN');
                //break;
            }
        }
        M()->commit();
    }catch (\Exception $e){
        M()->rollback();
    }
}

图片描述
在此过程中,用户反馈收到三条重复推送,分别对应上面红框中的两次任务推送和mysql恢复正常之后的第一次推送。
希望大佬解答一下原因和解决方法

阅读 1.6k
1 个回答

如果是全表扫描,就是表锁了。看下执行计划

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题