前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在 Laravel 中当 MySQL 异常宕机时强制返回空数据

在 Laravel 中当 MySQL 异常宕机时强制返回空数据

作者头像
seth-shi
发布2023-12-18 14:33:03
1060
发布2023-12-18 14:33:03
举报
文章被收录于专栏:seth-shi的专栏seth-shi的专栏

起因

  • 之前线上遇到一个问题, 就是当MySQL挂了, 然后导致整个服务崩塌, Redis在前面完全没分担任何压力.
  • 业务常规的查询逻辑如下:
    1. redis中获取数据, 有则返回
    2. 当第一步redis无数据, 去MySQL查询数据
    3. 把第二步查询到的数据写入redis
    4. 返回数据

问题分析

  • redis当然不会有问题, 问题是在第二步的时候
  • MySQL查询数据,数据库服务已经宕机, 这时候请求阻塞住
  • 阻塞超时,然后抛出异常,导致无法走到第三步
  • 下一次请求来, 又继续去连接MySQL,无限阻塞,把业务服务器也拖垮

解决方案

  • 这是我们的解决方案, 不一定适合所有业务. 当MySQL宕机强制缓存空数据到redis,允许部分页面为空.而不是无法提供服务

解决思路

  • 设置好合理的MySQL连接超时时间
    • mysqlnd.net_read_timeout = 3
    • 当数据库连接超时之后, 抛出异常
  • 新建一个基础模型BaseModel, 其它所有模型继承这个模型, 并重写newEloquentBuilder方法
代码语言:javascript
复制
<?php

namespace App\Models;


use Illuminate\Database\Eloquent\Model;

class BaseModel extends Model
{
    public function newEloquentBuilder($query)
    {
        return new MysqlCustomBuilder($query);
    }
}
  • 新建一个查询构造器类MysqlCustomBuilder
代码语言:javascript
复制
<?php

namespace App\Models\Database;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class MysqlCustomBuilder extends Builder
{
    public function get($columns = ['*'])
    {
        try {
            return parent::get($columns);
        } catch (\Exception $e) {

            // 根据 laravel 重连的错误码
            $message = $e->getMessage();
            if (Str::contains($message, [
                'server has gone away',
                'no connection to the server',
                'Lost connection',
                'is dead or not enabled',
                'Error while sending',
                'decryption failed or bad record mac',
                'server closed the connection unexpectedly',
                'SSL connection has been closed unexpectedly',
                'Error writing data to the connection',
                'Resource deadlock avoided',
            ])) {
                // 记录日志, 通知xxx
                // Log::error($e);
                // 强制返回空集合
                return Collection::make();
            }

            // 如果不在处理的范围内, 继续抛出异常
            throw $e;
        }
    }
}
  • 之后需要重点监控日志报错, 来确定页面为空是运营配置的问题还是数据库异常的问题
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-06-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 起因
  • 问题分析
  • 解决方案
  • 解决思路
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档