zoukankan      html  css  js  c++  java
  • python MySQLdb 如何设置读超时read_timeout

    在python中,经常用到 MySQLdb操作MySQL数据库。
    在实现上,MySQLdb并不是纯python的,而是封装了MySQL C API库_mysql

    对于MySQLdb是否支持read_timeout,其使用手册中对这个参数只字未提。所以,read_timeout是否真的可用,是存在疑惑的。stack overflow上面也有人问到同样的问题

    接下来,我们从MySQLdb的源码库MySQLdb-python github地址开始,看下是否支持read_timeout

    MySQLdb的源码

    先看下代码库中的HISTORY文件:

    beta 4
    ======
    
    Added support for the MySQL read_timeout option. Contributed by
    Jean Schurger (jean@schurger.org).
    
    Added a workaround so that the MySQL character set utf8mb4 works with Python; utf8 is substituted
    on the Python side.
    

    其中,已经明确提到,已经对参数read_timeout提供了支持。

    再来看下,底层代码是如何实现的_mysql.c:

    /* According to https://dev.mysql.com/doc/refman/5.1/en/mysql-options.html
       The MYSQL_OPT_READ_TIMEOUT apear in the version 5.1.12 */
    #if MYSQL_VERSION_ID > 50112
    #define HAVE_MYSQL_OPT_TIMEOUTS 1
    #endif
    
    
    #ifdef HAVE_MYSQL_OPT_TIMEOUTS
    	if (read_timeout) {
    		unsigned int timeout = read_timeout;
    		mysql_options(&(self->connection), MYSQL_OPT_READ_TIMEOUT,
    				(char *)&timeout);
    	}
    	if (write_timeout) {
    		unsigned int timeout = write_timeout;
    		mysql_options(&(self->connection), MYSQL_OPT_WRITE_TIMEOUT,
    				(char *)&timeout);
    	}
    #endif
    

    从代码中,可以看到,MySQL从5.1.12版本开始支持read_timeout.

    MySQLdb在具体实现上,通过
    mysql_options()设置参数MYSQL_OPT_READ_TIMEOUT,来实现读超时。

    关于MYSQL_OPT_READ_TIMEOUTMYSQL_OPT_WRITE_TIMEOUT,可以参考MySQL官方文档说明
    mysql_options()

    下面来看下MySQLdb-python中的read_timeout如何使用。

    read_timeout例子

    下面例子中,设置read_timeout为5s, 并使sql语句执行超过5s。
    查看其执行结果。

    import MySQLdb
    from datetime import datetime
    
    
    host = "127.0.0.1"
    port = 3306
    sql = "select sleep(10)"
    user = "root"
    passwd = "Aa123456"
    
    conn = MySQLdb.connect(host=host, port=port, user=user,passwd=passwd, connect_timeout=2, read_timeout=5, charset="utf8")
    cursor = conn.cursor()
    
    print("now:", datetime.now())
    
    try:
            cursor.execute(sql)
    except Exception as e:
            print("now:", datetime.now())
            print("except:", e)
            raise
    
    ret = cursor.fetchone()
    print("result:", ret)
    
    cursor.close()
    conn.close()
    print("end")
    

    output:

    now: 2019-07-28 15:57:40.424942
    now: 2019-07-28 15:57:45.425193
    except: (2013, 'Lost connection to MySQL server during query')
    Traceback (most recent call last):
      File "read_timeout.py", line 19, in <module>
        cursor.execute(sql)
      File "/Users/lanyang/workspace/orange-service/.venv/lib/python3.6/site-packages/MySQLdb/cursors.py", line 198, in execute
        res = self._query(query)
      File "/Users/lanyang/workspace/orange-service/.venv/lib/python3.6/site-packages/MySQLdb/cursors.py", line 304, in _query
        db.query(q)
      File "/Users/lanyang/workspace/orange-service/.venv/lib/python3.6/site-packages/MySQLdb/connections.py", line 217, in query
        _mysql.connection.query(self, query)
    MySQLdb._exceptions.OperationalError: (2013, 'Lost connection to MySQL server during query')
    

    可以看到,当sql语句执行超过5s后,连接被断开。
    已经达到预期的效果。

    参考

    Python 操作 MySQL 数据库

    MySQLdb-python安装

    MySQLdb-python使用文档

    MySQLdb-python github地址

    MySQL C API

  • 相关阅读:
    [考试]20150811
    [考试]20150810
    [随笔]暑假过了,暑假来了
    [考试]20150808
    动态规划大合集II
    [知识点][旧版]C++中的运算符
    NOIP动态规划大合集
    [考试]20150729
    [考试]20150728
    /=============分隔线=============/
  • 原文地址:https://www.cnblogs.com/lanyangsh/p/11259426.html
Copyright © 2011-2022 走看看