2017-08-06 82 views
1

我們嘗試在我們的Django(== 1.11.4)環境中使用PyMySQL(== 0.7.11)。但是,當多個操作同時執行時(遇到多個請求發送到相同的API函數),我們遇到了問題。PyMySQL與Django,多線程應用程序

pymysql.err.InternalError: Packet sequence number wrong - got 6 expected 1

我們正試圖從DB(一段時間內大量請求來自多個用戶)刪除記錄:

我們得到這個錯誤。

代碼:

def delete(self, delete_query): 
    self.try_reconnect() 
    return self._execute_query(delete_query) 

def try_reconnect(self): 
    if not self.is_connected: 
     self.connection.ping(reconnect=True) 

@property 
def is_connected(self) 
    try: 
     self.connection.ping(reconnect=False) 
     return True 
    execpt: 
     return False 

def _execute_query(self, query): 
    with self.connection.cursor() as cursor: 
     cursor.execute(query) 
     self.connection.commit() 
     last_row_id = cursor.lastrowid 
    return last_row_id 

我不認爲有必要指出的是,這些功能是DBHandler類, 和self.connection在初始化高清連接(個體經營)功能的一部分。

def connect(self): 
    self.connection = pymysql.connect(...) 

此連接功能運行一次在Django的啓動,我們創建DBHandler的全局實例(varaible)爲整個項目,並導入多個文件了。

我們使用刪除函數作爲我們的網關來執行刪除查詢。

我們在做什麼錯了?我們如何解決它?

+0

你還沒有說過是什麼問題。爲什麼直接使用連接,而不是使用Django的orm? –

+0

我們正在寫入已經存在的DB(不是我們的)。 問題是我們在執行並行操作時收到異常。 例外類型: 1. InternalError:數據包序列號錯誤 2. AttributeError:'NoneType'對象沒有屬性'timeout' – SpazaM

回答

1

發現問題,

PyMySQL是not thread safty分享,因爲我們沒有連接(我們共享多個文件作爲一個全球性的實例之間的類的實例 - 該類中只有一個連接),它被標有作爲1 :

threadsafety = 1

根據PEP 249

1 - Threads may share the module, but not connections.

一個在PyMySQL GitHub的問題的意見:

you need one pysql.connect() for each process/thread. As far as I know that's the only way to fix it. PyMySQL is not thread safe, so the same connection can't be used across multiple threads.

任何方式,如果你正在考慮使用其他的Python包叫做MySQLdb的爲您的線程的應用程序,通知MySQLdb的消息:

Don't share connections between threads. It's really not worth your effort or mine, and in the end, will probably hurt performance, since the MySQL server runs a separate thread for each connection. You can certainly do things like cache connections in a pool, and give those connections to one thread at a time. If you let two threads use a connection simultaneously, the MySQL client library will probably upchuck and die. You have been warned. For threaded applications, try using a connection pool. This can be done using the Pool module.

最終我們成功地使用Django ORM,我們只是寫我們的具體表格,使用inspectdb進行管理。