使用sqlalchemy操作pymysql的一些报错解决
.
.
.
使用sqlalchemy模块连接数据库并执行orm语句时报错
# 报错pymysql AttributeError: 'NoneType' object has no attribute 'settimeout'
解决思路:
有时候能取到结果有时候取不到,而且同一个请求不能稳定复现报错
感觉是没有获取到mysql的链接所以拿不到数据,就none type了
而且看监控timewait 很高
看mysql服务器端的日志,Got an error reading communication packets
表示:连接没有成功建立就被mysql kill了
改了mysql的设置:链接等待时长、最大连接数等参数,都没有效果
调整调用方式:不再大量调用
大量调用报错很多,单线程调用量少的时候报错量减少
原因:
因为并发抢资源,没有拿到链接,报错
并发拿不到链接的可以wait,但是超时就会被kill
改变MySQL服务器选项,增加值net_read_timeout和max_allowed_packet,
临时设置:
set global net_read_timeout = 200
set global max_allowed_packet= 20M
查看结果:
SHOW VARIABLES LIKE '%net_read_timeout%'
SHOW VARIABLES LIKE '%max_allowed_packet%'
# 该方法不是好的解决办法!!!
.
.
.
参考博客 https://www.cnblogs.com/cuitang/p/16669598.html
参考博客 https://www.cnblogs.com/cuitang/p/16669598.html
.
.
.
出现这个报错的本质原因是 多线程供共用连接,而链接关了成了none
# 可能得原因为:
视图函数中使用数据库连接池对象后,视图函数结束没有主动关闭掉该链接,可能造成了连接泄露!!!
要么自己在每一个使用连接对象的试图函数里手动关闭,注意一定要确保后续不用了连接对象了,
再关不然你连接对象关掉了,后续又操作数据库,就会出报错!!!
要么在请求扩展里面,当视图函数执行完后,关掉链接对象,这种比较方便!!!
@app.teardown_request
def teardown(e):
if e:
logger.error(
'出错的信息是%s' % (str(e)))
db_session.close() # 这样每个视图函数运行完,到这都会关闭掉该使用的数据库连接
# 避免了连接泄露!!!
# 在sqlalchemy的官方文档里是这样说的:
我们使用了 Session 对象,也就是说,我们没有使用 with 声明,
如果我们这样做的话,在请求完成后,我们最好明确地关闭 Session 。
flask处理全局异常的方法
参考博客 https://blog.csdn.net/qq_30966497/article/details/100101958
封装一个方法 用这个
@app.errorhandler(Exception)
def handle_error(e):
logger.error(
'出错的信息是%s' % (str(e)))
-------------------------------------------
import json
from werkzeug.exceptions import HTTPException
from flask import make_response
from mongoengine import ValidationError
from mongoengine.errors import NotUniqueError
class ApiError(HTTPException):
def __init__(self, msg='', error_code=4600):
HTTPException.__init__(self)
self.response = make_response(msg)
self.response.status_code = error_code
class GeneralError(ValueError): # 这个是有用的,可以直接使用
pass
def register_error_handlers(app):
"""注册错误处理函数
"""
config = [
(ValidationError, ErrorHandler.mongo_error),
(NotUniqueError, ErrorHandler.mongo_unique),
(GeneralError, ErrorHandler.general_error),
]
for error, handler in config:
app.register_error_handler(error, handler)
return
class ErrorHandler(object):
"""错误处理函数工具
"""
@staticmethod
def mongo_error(e):
"""mongoengine error handler func.
"""
msg = json.dumps(e.message)
error_code = 4602
resp = make_response(msg)
resp.status_code = error_code
return resp
@staticmethod
def mongo_unique(e):
"""处理字段unique的情况
"""
msg = json.dumps(e.args)
error_code = 4602
resp = make_response(msg)
resp.status_code = error_code
return resp
@staticmethod
def general_error(e):
"""处理一般的情况
"""
msg = json.dumps(e.args) # 由于e.args为元组,dumps之后变成了列表
error_code = 4600
resp = make_response(msg)
resp.status_code = error_code
return resp
@staticmethod
def schema_error(e):
"""处理marshmallow的情况
"""
msg = json.dumps(e.messages)
error_code = 4601
resp = make_response(msg)
resp.status_code = error_code
return resp
连接对象点close方法与连接对象点remove方法的区别
使用flask的sqlalchemy模块创建出连接对象与数据库连接池后,
连接对象点close方法与连接对象点remove方法的区别
在使用 Flask SQLAlchemy 模块时,创建的连接对象和数据库连接池是两个不同的概念。
连接对象(Connection Object):连接对象表示与数据库的单个连接。在 Flask SQLAlchemy 中,
连接对象通常是通过调用 create_engine() 方法创建的。连接对象用于执行具体的数据库操作,
例如执行查询、插入、更新或删除等操作。连接对象通常在使用完毕后需要关闭,以释放资源。
close() 方法:close() 方法用于关闭连接对象,即关闭与数据库的连接。当你调用 connection.close() 后,连接对象将不再可用,并且无法再执行任何数据库操作。
关闭连接对象可以释放数据库连接资源,确保不会出现连接泄露的问题。
在每次使用完连接对象后,最好调用 close() 方法关闭连接。
remove() 方法:remove() 方法用于将连接对象从连接池中移除。当你调用 pool.remove(connection)
后,连接对象将从连接池中移除,并且连接池中将会有一个可用连接数减少。
这个方法通常在你需要手动管理连接池的情况下使用,例如在多线程或异步环境中。
总结来说,close() 方法用于关闭连接对象,释放与数据库的连接,
而 remove() 方法用于将连接对象
从连接池中移除。这两个方法都是为了管理和释放连接资源,
确保数据库连接的正常运行和避免连接泄露的问题。
数据库连接池(Database Connection Pool):
数据库连接池是一组预先创建的数据库连接的集合,它们可以被重复使用以提高数据库访问性能和效率。
在 Flask SQLAlchemy 中,你可以通过配置
SQLALCHEMY_POOL_SIZE、
SQLALCHEMY_POOL_TIMEOUT、
SQLALCHEMY_POOL_RECYCLE、
等参数来设置连接池的大小和超时时间。
注意我们是不需要自己创建数据库连接池的,你用flask-sqlalchemy模块,会自动帮你创建池的,你配置文件写好控制参数即可,
reentrant call inside <_io.BufferedReader name=832>
'NoneType' object has no attribute 'settimeout'
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
# 暂时先连本地库 使用sqlalchemy自带的数据库连接池!!!
engine = create_engine(
'mysql+pymysql://root:333@127.0.0.1:3306/teng1?charset=utf8',
max_overflow=50, # 超过连接池大小后,还可以再创建的连接数,当这些额外的连接回收到连接池后将会被断开和抛弃。
pool_size=100, # 连接池大小,设大点,不设置默认为5太小了!!!设置为0表示没有大小限制 mysql能运行的最大连接数16384
pool_timeout=600, # 池中没有线程最多等待的时间,默认是30s,还拿不到就报错,时间设长点10分钟
pool_recycle=1800, # 该连接半小时后,对该连接的回收,再创一个新的连接,-1表示不回收一直用
)
Session_factory = sessionmaker(bind=engine) # Session类
db_session = scoped_session(Session_factory)
# 这样后
with db_session() as db:
在这里面写操作数据库的代码,这样数据库代码操作完了,会自动帮你把这个db对象关掉
不用自己手动去关了,这样上面的报错可能就不会出现了!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY