在查询期间与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 # 

你有什么主意吗?

mysql文档有一个专门针对这个错误的整个页面: http : //dev.mysql.com/doc/refman/5.0/en/gone-away.html

注意是

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

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

有三种方法可以放大mysql服务器的max_allowed_pa​​cket:

  1. 在mysql服务器上的文件/etc/mysql/my.cnf更改max_allowed_packet=64M并重启服务器
  2. 在mysql服务器上执行sql: set global max_allowed_packet=67108864;
  3. Python连接到mysql后执行sql:

connection.execute('set max_allowed_pa​​cket = 67108864')

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

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

您需要增加连接的超时时间。 如果因为某种原因你不能或不想这样做,你可以尝试拨打电话:

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

这将立即获取所有的结果,那么你的连接将不会中途迭代。

您也可以在forksubprocess的应用程序中遇到这个错误,所有这些错误都尝试使用与MySQL服务器相同的连接。 这可以通过为每个subprocess使用单独的连接来避免。

叉子可能会打你。 不要在这种情况下,但是。

我的情况是这个原因

错误2013(HY000):在查询期间与MySQL服务器失去连接

错误是我的表部分被损坏 。 我也无法mysqldump我的表,因为一些行破坏它。 这个错误与上面提到的任何内存问题无关。

好的是,MySQL给我返回了第一个失败的行号。 这是类似的东西

mysqldump:错误2013:丢失连接到MySQL服务器在查询时转储表mytable在行:12723

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

 SHOW CREATE TABLE mydatabase.mytable; 

随着我创build了新的表格。 我们称之为mytabletmp 。 然后复制你可以通过例如复制的行

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

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

彼得也有一些关于这个问题的很好的信息 。

将“max_allowed_pa​​cket”设置为64M,然后重新启动MySql服务器。 如果这不能解决你的问题,问题可能在别处。

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

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

这是发生在我用mariadb,因为我做了一个varchar(255)列一个unique key ..猜是太重了一个独特的,因为插入超时。

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

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

我也遇到类似的问题。 在我的情况下,通过以这种方式获得游标来解决这个问题:

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

在我的情况下,我遇到了这个问题,当发现一个SQL转储已经把表错误的顺序。 有问题的CREATE包含引用尚未创build的表的CONSTRAINT … REFERENCES。

我find了问题表,并将其CREATE语句移到违规表之上,并且错误消失了。

我遇到的另一个有关这个错误的转储错误是错误1005 /错误:150 – “无法创build表”,再次表的问题创build乱序。

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

改变我的CONSTRAINT名字解决了这个问题。

多处理和Django DB不能很好的一起玩。

我结束了在新的过程中closuresDjango 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) 

要么

Process.start()调用一个以开始的函数

其他一些build议使用

 from multiprocessing.dummy import Pool as ThreadPool 

它解决了我的(2013,丢失连接)问题,但线程使用GIL,当做IO时,在IO完成时释放它。

相比之下,stream程产生了一组互相沟通的工作人员,可能会比较慢。

我build议你花时间。 小技巧是使用scikit-learn项目支持的joblib 。 一些性能结果表明它执行本地池()..虽然它把责任编码器来validation真正的运行时间成本。

我遇到了同样的问题。 由于其他一些问题,我曾尝试将cnx.close()行添加到其他函数中。 相反,我删除了所有这些多余的closures,并像这样设置我的类:

 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() 

在这个类中调用的任何函数都是连接,提交和closures。