2009-12-10 68 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() 

被稱爲內這個類是連接時,提交,並關閉所有功能。

相關問題