查询期间失去与 MySQL 服务器的连接
Posted
技术标签:
【中文标题】查询期间失去与 MySQL 服务器的连接【英文标题】:Lost connection to MySQL server during query 【发布时间】:2010-12-25 11:39:49 【问题描述】:我有一个巨大的表,我需要处理其中的所有行。我总是收到这个丢失的连接消息,我无法重新连接并将光标恢复到它的最后一个位置。这基本上是我在这里的代码:
#
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
#
你有什么想法吗?
【问题讨论】:
从 connect() 调用中删除“cursorclass=MySQLdb.cursors.SSCursor”就足够了。它现在工作得很好。谢谢。 我遇到了同样的问题,但是我有大约 1B 行数据,所以我想使用 SSCursor 在 mysqld 端而不是我的 python 应用程序上缓存查询的数据。将 net_write_timeout 扩大到 1 小时解决了这个问题 :) 致从 Google 来到这里的人们:如果您使用多线程,则需要为每个线程提供自己的连接。 【参考方案1】:mysql 文档有一整页专门针对此错误: http://dev.mysql.com/doc/refman/5.0/en/gone-away.html
值得注意的是
如果您向服务器发送不正确或太大的查询,也可能会出现这些错误。如果 mysqld 收到一个太大或乱序的数据包,它会假设客户端出现问题并关闭连接。如果您需要大查询(例如,如果您使用大 BLOB 列),您可以通过设置服务器的 max_allowed_packet 变量来增加查询限制,该变量的默认值为 1MB。您可能还需要增加客户端的最大数据包大小。有关设置数据包大小的更多信息,请参见第 B.5.2.10 节“数据包太大”。
您可以通过使用 --log-warnings=2 选项启动 mysqld 来获取有关丢失连接的更多信息。这会在 hostname.err 文件中记录一些断开连接的错误
【讨论】:
另一个原因可能是mysqld崩溃了。【参考方案2】:mysql服务器的max_allowed_packet有三种放大方式:
-
在mysql服务器机器上修改
/etc/mysql/my.cnf
文件中的max_allowed_packet=64M
并重启服务器
在mysql服务器上执行sql:set global max_allowed_packet=67108864;
python连接mysql后执行sql:
connection.execute('set max_allowed_packet=67108864')
【讨论】:
【参考方案3】:对于派生子进程的应用程序,您也可能会遇到此错误,所有这些子进程都尝试使用与 MySQL 服务器的相同连接。这可以通过为每个子进程使用单独的连接来避免。
叉子可能会撞到你。不过在这种情况下请注意。
【讨论】:
是的,这对我来说是个问题。我正在使用 uwsgi 为我的烧瓶应用程序提供服务,并且在 uwsi 配置文件中,我将 processes 指令设置为 5。我将其更改为 1 并且它有效,但我不明白这个问题。每个进程不应该生成自己的连接吗? @Rockstar5645 这个问题是谁解决的? @vishal 我不记得了,但看起来我将进程指令从 5 更改为 1。【参考方案4】:确保在连接前关闭光标。我已经解决了我的问题:
if cur and con:
cur.close()
con.close()
【讨论】:
如果在连接之前关闭游标和连接,是不是一开始就无法连接?【参考方案5】:您需要增加连接的超时时间。如果由于某种原因您不能或不想这样做,您可以尝试致电:
data = db.query(sql).store_result()
这将立即获取所有结果,然后您的连接不会在遍历它们的中途超时。
【讨论】:
供参考和永久解决方案mysql docs 另请查看***【参考方案6】:我的情况是什么原因
ERROR 2013 (HY000): 查询期间丢失与 MySQL 服务器的连接
错误是我的表的某些部分损坏了。我也无法mysqldump
我的表,因为有些行破坏了它。
该错误与上述任何内存问题等无关。
好消息是 MySQL 向我返回了第一个失败的行号。有点像
mysqldump:错误 2013:在查询期间在第 12723 行转储表 mytable 时丢失与 MySQL 服务器的连接
解决方案是将数据复制到新表中。就我而言,我丢失了 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关于这个问题。
【讨论】:
【参考方案7】:这发生在我的 mariadb 上,因为我创建了一个 varchar(255)
列和一个 unique key
.. 猜想这对于一个独特的来说太重了,因为插入超时。
【讨论】:
【参考方案8】:多处理和 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)
或
Process.start()
调用一个以
其他一些建议使用
from multiprocessing.dummy import Pool as ThreadPool
它解决了我的(2013,丢失连接)问题,但是线程使用 GIL,在做 IO 时,会在 IO 完成时释放它。
相比之下,Process 会产生一组相互通信的工作人员,这可能会更慢。
我建议你计时。 一个小技巧是使用由 scikit-learn 项目支持的joblib。 一些性能结果表明它执行了本机 Pool().. 尽管它让编码人员负责验证真正的运行时间成本。
【讨论】:
> 多处理和 Django DB 不能很好地配合使用。今天也是这样,真是令人沮丧。 (2013, 'Lost connection to MySQL server during query') (2006, "MySQL server has gone away (BrokenPipeError(32, 'Broken Pipe'))") (ಥ﹏ಥ)【参考方案9】:将“max_allowed_packet”设置为 64M 并重新启动您的 MySql 服务器。如果这不能解决您的问题,则问题可能出在其他地方。
我有一个执行同时查询的多线程 php CLI 应用程序,我最近注意到了这个问题。现在对我来说很明显,MySql 服务器将来自同一 IP 的所有连接视为“单个”连接,因此只要单个查询完成,就会丢弃所有连接。
我想知道有没有办法让 MySql 允许来自同一个 IP 的 100 个连接,并将每个连接视为一个单独的连接。
【讨论】:
我不认为您关于“来自同一 IP 的所有连接都与 'sing'e' 连接”的说法是正确的。您可能会看到,因为 mysql 方法可能正在重用您的 PHP“线程”之间的持久连接。 "现在对我来说很明显,MySql 服务器将来自同一 IP 的所有连接视为“单个”连接" => 这当然是完全错误的,可以通过启动十并行 mysql 客户端进程在同一个机器上同时监控 mysql 连接 - 每个客户端当然都有自己的连接。【参考方案10】:如果有人或某事使用KILL command 终止您的连接,也会发生这种情况。
【讨论】:
【参考方案11】:当我尝试更新磁盘上的大小大于可用磁盘空间的表时,这发生在我身上。我的解决方案就是增加可用磁盘空间。
【讨论】:
【参考方案12】:在我的例子中,我在采购 SQL 转储时遇到了这个问题,该转储将表格放置在错误的顺序。有问题的 CREATE 包含一个 CONSTRAINT ... REFERENCES,它引用了一个尚未创建的表。
我找到了有问题的表,并将其 CREATE 语句移到有问题的表上方,错误消失了。
我遇到的与此错误转储有关的另一个错误是 ERROR 1005/errno: 150 -- "Can't create table" ,这又是表创建乱序的问题。
【讨论】:
【参考方案13】:我也遇到过类似的问题。就我而言,它是通过以这种方式获取光标来解决的:
cursor = self.conn.cursor(buffered=True)
【讨论】:
我使用的是 mysql.connector 而不是 MySQLdb【参考方案14】:与@imxylz 相同,但我必须使用mycursor.execute('set GLOBAL max_allowed_packet=67108864')
,因为在不使用 GLOBAL 参数的情况下出现只读错误。
mysql.connector.__version__
8.0.16
【讨论】:
【参考方案15】:当我的 CONSTRAINT
名称与其他 CONSTRAINT
名称相同时,我发生了这种情况。
更改我的CONSTRAINT
名称解决了这个问题。
【讨论】:
【参考方案16】:我遇到了同样的问题。由于其他一些问题,我曾尝试将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()
在此类中调用的任何函数都是连接、提交和关闭。
【讨论】:
【参考方案17】:当我尝试对数百万条记录进行批量插入时,我遇到了“管道损坏”的错误。我最终解决了这个问题,将我的数据分块成更小的批量大小,然后为我需要做的每个插入运行一个带有 mysql 游标的 executemany 命令。这解决了问题,并且似乎没有以任何明显的方式影响性能。
例如。
def chunks(data):
for i in range(0, len(data), CHUNK_SIZE):
yield data[i:i + CHUNK_SIZE]
def bulk_import(update_list):
new_list = list(chunks(update_list))
for batch in new_list:
cursor.execute(#SQL STATEMENT HERE)
【讨论】:
【参考方案18】:你可以看到我对类似问题的回答:
https://***.com/a/69610550/16647254
使用锁来解决这个问题
lock.acquire()
mysqlhelper.getconn()
result_db_num = mysqlhelper.update(sql, [businessid, md5_id])
mysqlhelper.end()
mysqlhelper.dispose()
lock.release()
【讨论】:
【参考方案19】:我在使用 mariadb
、sqlalchemy
和 pandas
时也遇到了同样的情况,就像上面的 @iamapotatoe
一样,我还创建了一个函数来将数据帧分解成块并将它们移植到 sql一点一点的数据库。
如果更改 mysql 配置选项中的 max_allowed_packet
对您不起作用,则可以使用此功能。
def load_large_df(table_name,df_to_load,batch_size,engine):
df_to_load = df_to_load.dropna(how='all')
with engine.connect() as conn:
conn.execute(f"DROP TABLE IF EXISTS table_name")
rows = df_to_load.shape[0]
batch = int(rows/batch_size)
strt = 0
while strt < rows:
df = df_to_load[strt:].head(batch)
df.to_sql(table_name,con=conn,if_exists='append')
strt += batch
【讨论】:
Pandas 已经提供了一个专用(和优化的)参数chunksize
来分块导入大型数据帧。【参考方案20】:
解决起来很简单,到你的phpadmin控制面板点击config/然后编辑你看到的.ini文件。查找端口 3306,如果这不是您用于连接的端口,请将 3306 更改为您正在使用的端口。在您的登录屏幕上,只需为您的服务器输入 localhost,如果它不是默认端口,或者您没有按原样更改 sql 配置 leavit 中的文件名 my.ini,则为您的端口。然后输入您的用户名:root 或您创建的用户名,然后输入密码:1234 或您分配的用户名。如果您正在本地连接,请不要检查 url 选项。然后键入要编辑的数据库的名称。注意:连接后,您将看到您的服务器或您要连接的服务器上的数据库列表。
【讨论】:
记得使用 % 赋予用户对你的表和数据库的通用访问权限 我不知道这个答案有什么关系。 OP 试图询问为什么他在执行查询时会失去连接。 这个答案是题外话。以上是关于查询期间失去与 MySQL 服务器的连接的主要内容,如果未能解决你的问题,请参考以下文章
错误代码:2013。查询期间丢失与 MySQL 服务器的连接
查询期间丢失与 MySQL 服务器的连接 - Python、MySql
Django OperationalError(2013,“查询期间丢失与 MySQL 服务器的连接”)
2013, '在查询期间丢失与 MySQL 服务器的连接 - Pymysql Microsoft sql server management Studio