2009-12-10 405 views
41

我有一个巨大的表,我需要处理其中的所有行。我总是得到这个Lost连接消息,我无法重新连接并将光标恢复到最后一个位置。这是基本的代码,我这里有:在查询过程中丢失与MySQL服务器的连接

# 
import MySQLdb 

class DB: 
    conn = None 

    def connect(self): 
    self.conn = MySQLdb.connect('hostname', 'user', '*****', 'some_table', cursorclass=MySQLdb.cursors.SSCursor) 

    def query(self, sql): 
    try: 
    cursor = self.conn.cursor() 
    cursor.execute(sql) 
    except (AttributeError, MySQLdb.OperationalError): 
    self.connect() 
    cursor = self.conn.cursor() 
    cursor.execute(sql) 
    return cursor 
# 

# 
db = DB() 
sql = "SELECT bla FROM foo" 
data = db.query(sql) 

for row in data: 
    do_something(row) 
# 

但我总是得到这样的:

# 
Traceback (most recent call last): 
    File "teste.py", line 124, in <module> 
    run() 
File "teste.py", line 109, in run 
    for row in data: 
File "/usr/lib64/python2.5/site-packages/MySQLdb/cursors.py", line 417, in next 
    row = self.fetchone() 
File "/usr/lib64/python2.5/site-packages/MySQLdb/cursors.py", line 388, in fetchone 
    r = self._fetch_row(1) 
File "/usr/lib64/python2.5/site-packages/MySQLdb/cursors.py", line 285, in _fetch_row 
    return self._result.fetch_row(size, self._fetch_type) 
    _mysql_exceptions.OperationalError: (2013, 'Lost connection to MySQL server during query') 
    Exception _mysql_exceptions.OperationalError: (2013, 'Lost connection to MySQL server during query') in <bound method SSCursor.__del__ of <MySQLdb.cursors.SSCursor object at 0x7f7e3c8da410>> ignored 
# 

你有什么想法?

+0

从connect()调用中删除“cursorclass = MySQLdb.cursors.SSCursor”就足够了。现在它工作得很好。谢谢。 – Otavio 2009-12-16 19:13:45

+0

我有同样的问题,但我有〜1B行数据,所以我想使用SSCursor缓存查询数据在mysqld端而不是我的python应用程序。 扩大net_write_timeout到1小时修复问题:) – cow 2017-07-08 16:38:21

回答

8

您需要增加连接的超时时间。如果你不能或不想做的,由于某种原因,你可以尝试致电:

data = db.query(sql).store_result() 

这将获取所有结果立即,那么你的连接不会半途迭代在他们超时。

+0

作为参考和永久解决方案[mysql文档](https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_connect_timeout ) – 2017-11-02 08:43:51

+0

也检查[stackoverflow](https://stackoverflow.com/a/6447452/1085495) – 2017-11-05 09:59:22

35

MySQL的文档有一整页专注于这个错误: http://dev.mysql.com/doc/refman/5.0/en/gone-away.html

注意

  • 如果你发送一个查询到这是不正确的服务器也可以得到这些错误或太大了。如果mysqld收到的数据包太大或失序,则认为客户端出现问题并关闭连接。如果您需要大量查询(例如,如果您使用大BLOB列),则可以通过设置服务器的max_allowed_pa​​cket变量(默认值为1MB)来增加查询限制。您可能还需要增加客户端上的最大数据包大小。有关设置数据包大小的更多信息在第B.5.2.10节“数据包太大”中给出。

  • 通过使用--log-warnings = 2选项启动mysqld,可以获得关于丢失连接的更多信息。这会记录hostname.err文件中的一些断开连接的错误。

+0

另一个原因可能是mysqld崩溃。 – automatthias 2013-04-06 20:49:02

11

确保在连接之前关闭光标。我已经解决了我的问题:

if cur and con:       
    cur.close() 
    con.close() 
3

将'max_allowed_pa​​cket'设置为64M并重新启动MySql服务器。如果这不能解决你的问题,那么问题可能在于别处。

我有一个多线程的PHP CLI应用程序,可以同时进行查询,我最近注意到了这个问题。现在很明显,MySql服务器将来自同一个IP的所有连接视为“单一”连接,因此只要一个查询完成,就会删除所有连接。

我想知道是否有办法让MySql允许来自同一IP的100个连接,并将每个连接视为单独的连接。

+2

我不认为你的声明“关于来自同一个IP的所有连接与'sing'e'连接”是正确的。您可能会看到,因为mysql方法可能会重复使用PHP“线程”之间的持久连接。 – pawstrong 2013-08-22 16:15:01

12

有三种方式扩大MySQL服务器的max_allowed_pa​​cket的:

  1. 变化max_allowed_packet=64M文件/etc/mysql/my.cnf MySQL服务器的机器上,然后重新启动服务器
  2. 执行MySQL服务器上的SQL:set global max_allowed_packet=67108864;
  3. Python在连接到mysql后执行sql:

connection.execute('set max_allowed_packet=67108864')

6

You can also encounter this error with applications that fork child processes, all of which try to use the same connection to the MySQL server. This can be avoided by using a separate connection for each child process.

叉子可能会打你。当然不要在这种情况下。

1

这是发生在我身上mariadb,因为我做了一个varchar(255)列a​​..猜测这是太重的独特,因为插入超时。

5

我我来说,我的

ERROR 2013 (HY000): Lost connection to MySQL server during query

错误的原因是我表的部分都损坏。我也无法mysqldump我的表,因为有些行破坏了它。 错误与上面提到的任何内存问题等无关。

好的是MySQL向我返回了第一个失败的行号。这是类似于

mysqldump: Error 2013: Lost connection to MySQL server during query when dumping table mytable at row: 12723

解决方案是将数据复制到一个新的表。在我的情况下,我失去了10行数据,因为我不得不跳过这些损坏的行。首先,我创建了一个“tmp”表格,其中包含旧的表格。 SHOW CREATE TABLE是你的朋友在这里。例如。

SHOW CREATE TABLE mydatabase.mytable; 

随着我创建了新表。我们称之为mytabletmp。然后复制您可以通过例如

insert into mysqltabletmp select * from mytable where id < 12723; 
insert into mysqltabletmp select * from mytable where id > 12733; 

之后,删除旧表,将tmp-table重命名为旧表名。

关于这个问题也有some nice Information from Peter

1

如果某人或某事使用KILL command杀死了您的连接,也会发生这种情况。

1

当我尝试更新磁盘上的大小大于可用磁盘空间的表时,发生了这种情况。对我来说,解决方案只是增加可用磁盘空间。

0

在我的情况下,当发现SQL转储发生错误的顺序放置表时,我遇到了这个问题。有问题的CREATE包含引用尚未创建的表的CONSTRAINT ... REFERENCES。

我找到了问题表,并将CREATE语句移到了冒犯者的上面,并且错误消失了。

我遇到的与此错误转储有关的其他错误是ERROR 1005/errno:150 - “无法创建表”,同样也是无序创建表的问题。

0

当我的CONSTRAINT名称与其他CONSTRAINT名称具有相同名称时,发生这种情况。

更改我的CONSTRAINT名称解决了此问题。

1

我也遇到过类似的问题。在我的情况下,它解决了通过获取光标这样:

cursor = self.conn.cursor(buffered=True) 
+0

我正在使用mysql.connector而不是MySQLdb – user6938211 2016-10-07 16:05:58

0

多处理和Django的DB不玩好起来。

我最终在新进程中关闭了Django DB连接的第一件事。

因此,一个不会引用父级使用的连接。

from multiprocessing import Pool 

multi_core_arg = [[1,2,3], [4,5,6], [7,8,9]] 
n_cpu = 4 
pool = Pool(n_cpu) 
pool.map(_etl_, multi_core_arg) 
pool.close() 
pool.join() 

def _etl_(x): 
    from django.db import connection 
    connection.close() 
    print(x) 

OR

Process.start()调用与

其他一些建议使用

from multiprocessing.dummy import Pool as ThreadPool 

启动功能,这解决了我(2013年,失去连接)的问题,但线程使用GIL ,当做IO时,要在IO完成时释放它。

比较而言,Process会产生一组互相沟通的工作人员,这可能会比较慢。

我建议你定时。 一个小技巧是使用joblib这是scikit学习项目的支持。 一些性能结果表明它执行本地池()..尽管它将责任留给编码器来验证真正的运行时成本。

0

我遇到了同样的问题。由于其他一些问题,我试图添加cnx.close()行到我的其他功能。相反,我删除了所有这些无关的关闭和设置我的阶级是这样的:

class DBase: 

config = { 
     'user': 'root', 
     'password': '', 
     'host': '127.0.0.1', 
     'database': 'bio', 
     'raise_on_warnings': True, 
     'use_pure': False, 
     } 

def __init__(self): 
    import mysql.connector 
    self.cnx = mysql.connector.connect(**self.config) 
    self.cur = self.cnx.cursor(buffered=True) 
    print(self.cnx) 
def __enter__(self): 
    return DBase() 

def __exit__(self, exc_type, exc_val, exc_tb): 
    self.cnx.commit() 
    if self.cnx: 
     self.cnx.close() 

被称为内这个类是连接时,提交,并关闭所有功能。

相关问题