V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
miniyao
V2EX  ›  Python

MySQL- Python 建立的 db.connect() 需要每次关闭吗?

  •  
  •   miniyao · 2019-03-21 22:41:02 +08:00 · 9512 次点击
    这是一个创建于 1834 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一个 while 循环业务,每 10 分钟去请求一下,发现有数据更新了,就抓过来存到 MySQL 中去。

    import MySQLdb
    db = MySQLdb.connect(host='localhost', port=3306, user='xxx', passwd='xxx', db='xxx_DB', charset='utf8')
    cursor = db.cursor() 
    # do something...
    db.commit()
    

    请教:每次把数据存到 MySQL 中去了之后,要用 db.close()吗?

    1、如果没有 db.close(),多长时间之后,这次连接会自动 close 掉?
    2、如果不执行 db.close(),因为是个 while 循环,是不是每次都会重新建立一个 db 连接?
    3、如果每次都执行 db.close(),那么下次又要重新建立连接,这样性能有多大损耗?

    33 条回复    2019-04-01 13:22:01 +08:00
    CallMeReznov
        1
    CallMeReznov  
       2019-03-21 23:07:50 +08:00   ❤️ 12
    啊...看到楼主的问题仿佛遇到了 5 年前的自己.

    1.超时时间设置
    2.连接数一般是有限的,你只建立不释放的后果就是在超时时间内达到最大连接数会导致你无法继续
    3.比起上面两个造成的问题,建立-执行-关闭,这都属于正常的负载范围,如果你的数据库载体这点操作都无法顺利进行你就地想办法优化提升你的服务器处理能力或者优化你的 SQL 语句了
    Northxw
        2
    Northxw  
       2019-03-22 00:21:11 +08:00   ❤️ 6
    额,仿佛看到大二的自己...

    简单来说,构造一个数据库的类,在__init__中初始化,在__del___中自动关闭数据库连接,再设置一个只进行插入操作的函数。 最后生成一个类的实例,While 定时循环调用实例中插入操作函数,应该就 OJBK 了。大概这样:

    class Save(object):
    def __init__(self):
    self.localhost = 'localhost'
    self.user= 'root' # 或者其他
    self.pass_ = 'xxxx'
    self.port= 3306
    self.db= 'database_name'

    def __del__(self):
    self.db.close()

    def save(self):
    pass

    if main == '........'(忘了):
    save_mysql = Save()
    while True:
    save_mysql.save()
    hcymk2
        3
    hcymk2  
       2019-03-22 00:30:20 +08:00 via Android   ❤️ 2
    用链接池
    zjp
        4
    zjp  
       2019-03-22 00:42:05 +08:00 via Android   ❤️ 4
    同仿佛大二的自己…
    MySQL 会自动关闭空闲 8 小时的连接,这个时间由 wait_timeout 配置。貌似多数数据库不会自动关闭
    3. 一般程序都会用连接池,不过 10 分钟才一次的随便了……毕竟有些连接池默认 30 分钟也会全部重新连接或者直接 close
    kernel
        5
    kernel  
       2019-03-22 06:36:52 +08:00 via Android
    10 分钟一次就重新连就行了。你想想很早以前用 PHP 写网页,每一个请求都重新连一下,你这 10 分钟一次频率算个鸟。
    ericgui
        6
    ericgui  
       2019-03-22 06:49:35 +08:00   ❤️ 5
    @CallMeReznov 一个氛围良好的社区就应该多一些这样的人 @Livid

    最近 v 站太多乱七八糟、阴阳怪气的沙雕了
    ericgui
        7
    ericgui  
       2019-03-22 06:50:21 +08:00
    @CallMeReznov
    @Northxw
    @zjp

    良好氛围的创造,离不开这样的人,+10086
    fngtz
        8
    fngtz  
       2019-03-22 08:28:05 +08:00 via iPhone
    @Northxw python 一般不用 del。需要 clos 的对象 e 可以用上下文( enter,exit )。
    Torpedo
        9
    Torpedo  
       2019-03-22 08:54:47 +08:00 via Android
    这个帖子好和谐
    Sothoth
        10
    Sothoth  
       2019-03-22 09:01:23 +08:00
    加个装饰器
    Northxw
        11
    Northxw  
       2019-03-22 09:05:25 +08:00
    @fngtz 额,还好吧,我一直在用,哈哈,🤝
    coolair
        12
    coolair  
       2019-03-22 09:11:12 +08:00 via Android
    如果是循环插数据,可以先把数据放列表,然后一次插入多条数据,如果数据量大,可以设置一个长度,比如 500 条写一次数据库。
    David1119
        13
    David1119  
       2019-03-22 09:15:56 +08:00
    推荐直接使用 sqlalchemy 的连接池,性能很好,可以用 orm,也可以直接用 raw sql。
    另外 django 遇到高并发问题性能不行,用 sqlalchemy 替代原来的 connection 并加上连接池,性能翻倍。
    zuoakang
        14
    zuoakang  
       2019-03-22 09:19:15 +08:00 via Android
    连接池有用
    ctro15547
        15
    ctro15547  
       2019-03-22 09:28:58 +08:00
    刚开始学的话可以不停重连关闭没关系,用学校的电脑数据库一般处理能力每秒几千莫得问题,可以不用担心性能问题
    inhzus
        16
    inhzus  
       2019-03-22 09:29:20 +08:00 via Android
    一定要记得 close 的。去年有个大一的学弟一起做个项目,好好的突然怎么都不能连接数据库。后来查日志发现他代码全部都是只管 connect 不管 close,超过最大连接数就凉凉。
    dnsaq
        17
    dnsaq  
       2019-03-22 09:32:20 +08:00 via iPhone
    首先不要想着 mysql 自动帮你关闭因为实际没有屁用甚至会把业务搞崩,自己骗自己,严格要求自己 colse 或者连接池,我公司的程序天天报超出 max con 还找运维的问题
    wly19960911
        18
    wly19960911  
       2019-03-22 09:38:39 +08:00
    连接池管理 sql 的连接 ,连接池会保持几条连接,并且根据并发会新开到一定限制数量的连接,然后会自己关闭,你只需要从连接池拿连接就好,自己不用创建连接。
    Nicoco
        19
    Nicoco  
       2019-03-22 09:46:13 +08:00
    SQLAlchemy 值得选择
    suueyoung
        20
    suueyoung  
       2019-03-22 09:52:30 +08:00
    with statement
    fngtz
        21
    fngtz  
       2019-03-22 09:59:59 +08:00
    Northxw
        22
    Northxw  
       2019-03-22 10:05:12 +08:00
    @fngtz 🤝
    qq976739120
        23
    qq976739120  
       2019-03-22 10:17:15 +08:00
    用链接池也要 close 的.....
    wuyue92tree
        24
    wuyue92tree  
       2019-03-22 11:49:01 +08:00
    连接池 + 单例模式建立 mysql 对象
    不 close,时间久了,TCP 链接会多到爆,性能杀手
    joyc
        25
    joyc  
       2019-03-22 13:17:42 +08:00 via Android
    @Torpedo 和谐到大家都找回了年轻时的自己
    aploium
        26
    aploium  
       2019-03-22 13:39:26 +08:00
    可以用 sqlalchemy 自带的连接池, 如
    engine=sqlalchemy.create_engine(DB_URL)
    result_proxy=engine.execute('some sql')
    rows=result_proxy.fetchall()

    不用专门去考虑连接池和释放的问题, 里面内置了
    1762628386
        27
    1762628386  
       2019-03-22 15:15:26 +08:00
    啊...看到楼主的问题仿佛遇到了 4 年前的自己.

    换个思路,只去判断是否抓取即刻,10 分钟的定时交给外部命令:crontab supervise,做好进程监控。
    hayi
        28
    hayi  
       2019-03-22 15:38:48 +08:00
    torndb 模块可以解决
    Vegetable
        29
    Vegetable  
       2019-03-22 16:08:46 +08:00   ❤️ 1
    我...不回忆能回答问题吗?

    我举个例子

    比如我想上厕所需要纸
    纸是公司提供的,放在行政那里

    好,现在问题变了:

    我上厕所用完纸需要每次都给让行政拿回去吗?

    正常情况下,还与不还都无所谓,因为你不叫她过来拿,过了 8 小时(默认可配置)不用的话行政小妹会自己从我兜里拿走.
    有些程序没处理这情况,以为自己有纸,就出现了裤子都脱了最后发现:"卧槽我纸呢?!"程序报错(2006 gone away).

    所以如果不是特别高的负载,就还回去好了.

    那么如果负载特别高呢?比如拉肚子了一天去很多次,还来还去的太麻烦了,耽误事憋不住不就完了吗?
    这情况能不还就不还了,影响性能.

    离得近的几个人成立了一个小组共同保管 3 包纸(连接池),同时有一个小弟负责和行政沟通纸的一切事宜,那么组里别人就不用管纸的事情了,一伸手就肯定有.

    所以没什么标准答案,合适就好.最简单就是每次都重新打开一个,用完关了.建议从这个方案开始
    Raymon111111
        30
    Raymon111111  
       2019-03-22 16:22:46 +08:00
    用连接池, 不要自己管理这个.

    如果是学习的目的可以仔细研究研究.
    boxvivi007
        31
    boxvivi007  
       2019-03-22 20:00:37 +08:00
    为什么不用 with 语句自动管理上下文
    fngtz
        32
    fngtz  
       2019-04-01 09:46:48 +08:00 via iPhone
    @Northxw 哎呀,我之前的想法不太对。虽然正常不用 del,但是数据库属于特殊的领域。sqlalchemy 就是在连接池对象的__del__里面关闭数据库连接的。
    Northxw
        33
    Northxw  
       2019-04-01 13:22:01 +08:00
    @fngtz 哦豁? 还惦记着啊。🤝
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1525 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 67ms · UTC 23:57 · PVG 07:57 · LAX 16:57 · JFK 19:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.