最近在项目中,我使用 Django Command 模块写了一个脚本,处理从 MQ 发来的消息,并入库。在测试过程中,程序运行良好,但是在程序上线并运行一段时间后,出现了以下错误:

OperationalError: (2006, 'MySQL server has gone away')

发现问题

经过一段时间的排查后,我发现了问题的原因:因为我要入库的消息并不频繁,所以我的程序的入库操作之间可能会间隔一段时间,而当这段时间大于 MySQL 配置的超时时间后,MySQL 便会主动断开与该程序的连接;此时,程序做数据库相关操作,则会发现数据库连接已经失效,因而报 MySQL server has gone away的异常。

查看 MySQL 配置的超时时间方法为:

show variables like 'wait_timeout';

分析问题

在网上搜索相关问题后,我发现有很多人问过相关问题,而 Django 官网的这个讨论,给了我很大帮助。

处理方法有两个:

1) 每次调用完 Model 后,手动关闭 connection

from django.db import connection

connection.close()

2) 调整数据库的超时时间(不推荐!)

但是,这两个都不适合我的程序:

  • 方法1是针对 Model 操作间隔一定很长的情况,如果某个时间段内需要很频繁的操作数据库,那么频繁关闭-新建数据库连接无疑是低效的。而且,connection 是与默认的数据库的连接,即 settings 中定义的 default 数据库。如果项目配置了多个数据库(列如主从数据库),那么 connection.close()则不能与关闭其他数据库的连接,问题仍未解决。
  • 方法2直接修改数据库超时时间,很容易影响别的服务,会带来很多潜在的问题。

针对我的情况,我参考了 Django 源码涉及数据库连接维护的部分。

在 django.db.__init__.py 中,有以下代码片段:

# Register an event to reset transaction state and close connections past
# their lifetime.
def close_old_connections(**kwargs):
for conn in connections.all():
conn.close_if_unusable_or_obsolete()
signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)

可见,Django 将请求开始和请求结束信号绑定给了 close_old_connections函数,每当有请求开始和结束以后,Django 都会检查目前有没有失效的连接,如果有的话就将其关闭。通过这种办法,Django 保证处理请求时,数据库连接都是可用的,不会出现我遇到的问题;而我的程序在涉及 Model 操作时,没有检查连接的有效性,因而出现了题目中的错误。

解决问题

在定位到问题且知道处理方法后,接下来的工作就非常简单了。 仿照上述代码,定义函数:

from django.db import connections

def close_old_connections():
for conn in connections.all():
conn.close_if_unusable_or_obsolete()

然后在每次 Model 操作前调用close_old_connections()就解决问题了。

James Zhao

Henry Zhu • 2 months ago
还有一种解决办法, 在Django中修改pool_recycle的值, 让它小于mysql的wait_timeout, 保证conn的实效性.
但我还在尝试中, 要是成功了, 回来留言.

•Reply•Share ›
Avatar
zhaojames0707 Mod Henry Zhu • 2 months ago
等你的好消息:)

•Reply•Share ›
Avatar
Henry Zhu zhaojames0707 • 2 months ago
本来想直接设置CONN_MAX_AGE, 让它比wait_timeout小就行了. 后来发现, 像你文档说的, 只有request_started和request_finished的时候, 才会用到CONN_MAX_AGE..
看来只能在任务开始和结束的时候, 手动调用close_old_connections了.
---
但是你为什么重新写了close_old_connections呢(和`django.db.__init__.py`中的好像一模一样)?

•Reply•Share ›
Avatar
zhaojames0707 Mod Henry Zhu • 2 months ago
哈哈,因为这个方法在文档里没有提到,担心Django后续会去掉或者改地方;可能担心多余了,直接用Django里的就好。

解决 django 中 mysql gone away 的问题的更多相关文章

  1. django中mysql数据库设置错误解决方法

    刚在django中settings.py进行设置mysql数据库. 当进行执行python manage.py shell命令时会报以下错误: 只需要在settings.py中 DATABASES = ...

  2. Django中MySQL读写分离技术

    最近需要用到Django的MySQL读写分离技术,查了一些资料,把方法整理了下来. 在Django里实现对MySQL的读写分离,实际上就是将不同的读写请求按一定的规则路由到不同的数据库上(可以是不同类 ...

  3. python基础[16]——解决django连接mysql数据库报错的问题

    Models.py #创建数据表 from django.db import models from django.utils import timezone from tinymce.models ...

  4. Django中MySQL事务的使用

    Django中事物的使用 from django.db import transaction @transaction.atomic通过transaction的@transaction.atomic装 ...

  5. 一篇文章解决django中时区问题

    首先要明确的是,当在Django项目的setting.py文件中设置了USE_TZ=True时,我们给定的时间存储到数据库的时候都会变成UTC时间(使用auto_now_add和auto_now为Tr ...

  6. Clojure:解决korma中mysql utf8的问题

    当使用korma内置的mysql方法时,无法添加utf-8的支持.解决的方法就是重写mysql方法,代码如下: (defn mysql "改编自korma,添加了utf-8的支持" ...

  7. 解决idea中mysql连接失败Could not create connection to database server. Attempted reconnect 3 times. Giving up.

    原因是少一个参数,设置时区的.  解决方法: 加一个参数: serverTimezone=UTC jdbc:mysql://localhost:3306/SshProject?useUnicode=t ...

  8. 解决WampServer中MySQL数据库中文乱码的问题

    原文地址:http://blog.csdn.net/qq756703833/article/details/37971057 左键点击托盘区的WampServer图标,选择MySQL--my.ini, ...

  9. 如何解决 Django中出现的 [Errno 13] Permission denied问题

    环境:linux 如果你使用了Apache部署了Django项目,在上传文件时可能会出现 “[Errno 13] Permission denied:某目录”的错误. 这是因为apache没有权限在该 ...

随机推荐

  1. 【转】vfork 和 fork的区别

    fork()与vfock()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别: 1.  fork  ():子进程拷贝父进程的数据段,代码段     vfork ( ):子进程与父进程共享数据段 ...

  2. python第一章计算机基础

    第一章 计算机基础 1.1 硬件 计算机基本的硬件由:CPU / 内存 / 主板 / 硬盘 / 网卡 / 显卡 / 显示器 等组成,只有硬件但硬件之间无法进行交流和通信. 1.2 操作系统 操作系统用 ...

  3. 高阶函数 map,reduce, filter的用法

    1. map 用法 def fun_C(x): """求平方""" return x ** 2 result = map(fun_C, my ...

  4. python+selenium之元素的八大定位方法

    以百度搜索框为例,先打开百度网页 1.点右上角爬虫按钮 2.点左下角箭头 3.讲箭头移动到百度搜索输入框上,输入框高亮状态 4.下方红色区域就是单位到输入框的属性: <input id=&quo ...

  5. JqueryValidate 修改 为根据ID验证

    <!--修改validate根据ID验证 --> <script type="text/javascript"> if ($.validator) { $. ...

  6. noi.ac NOIP2018 全国热身赛 第二场 T1 ball

    [题解] 可以发现每次推的操作就是把序列中每个数变为下一个数,再打一个减一标记:而每次加球的操作就是把球的位置加上标记,再插入到合适的位置. 用set维护即可. #include<cstdio& ...

  7. bzoj1455左偏树裸题

    #include <stdio.h> bool vi[1000010]; int n,de[1000010],ls[1000010],rs[1000010],va[1000010],fa[ ...

  8. linux中的命令

    1,ln-链接 功能是为某一个文件在另外一个位置建立一个同步的链接,这个命令最常用的参数是-s,具体用法是: ln -s 源文件 目标文件  // -s 是 symbolic(符号,象征)的意思. l ...

  9. 又一个ajax实例,结合jQuery

    又一个ajax实例,配合jQuery   html <!DOCTYPE html> <html lang="zh-cn"> <head> < ...

  10. Java度线程——生产消费问题

    /*JDK1.4版本:生产者,消费者.多生产者,多消费者的问题.if判断标记,只有一次,会导致不该运行的线程运行了.出现了数据错误的情况.while判断标记,解决了线程获取执行权后,是否要运行! no ...