2014-07-14 41 views
2

我正在運行多線程python腳本。它所做的是抓取網頁並將其插入/更新到MySQL中。這裏是我的代碼python:Mac OS X. malloc錯誤。被釋放的指針未被分配。中止陷阱6

mythread.py

import threading 
import time 

class MyThread (threading.Thread): 
    def __init__(self, threadID, threadname, q): 
     threading.Thread.__init__(self) 
     self.threadID = threadID 
     self.threadname = threadname 
     self.queue = q 
     self.__exitFlag = False 
     self.__signal_lock = threading.Lock() 

    def run(self): 
     print "Starting " + self.threadname 
     self.process_data() 
     print "Exiting " + self.threadname 

    def stop(self): 
     with self.__signal_lock: 
      self.__exitFlag = True 

    def process_data(self): 
     while not self.__exitFlag: 
      if not self.queue.empty(): 
       data = self.queue.get() 
       # crawl data from the web... 
       # update to mysql 
       # assuming we have already connected mysql: 
       # db = MySQLDb() 
       # db.connect 
       query = "" 
       db.query(query) 

mysql_db.py

class MySQLDb: 
    conn = None 

    def connect(self): 
     self.conn = MySQLdb.connect(
      host="127.0.0.1", 
      user = "root", 
      passwd = "password", 
      db = "moviestats") 

     self.cursor = self.conn.cursor(MySQLdb.cursors.DictCursor) 

    def query(self, sql): 
     try: 
      self.cursor.execute(sql) 
      self.conn.commit() 
     except (AttributeError, MySQLdb.OperationalError): 
      # solution to: MySQL server has gone away 
      self.cursor.close() 
      self.connect() 
      self.cursor = self.conn.cursor(MySQLdb.cursors.DictCursor) 
      self.cursor.execute(sql) 
      self.conn.commit() 

以下是錯誤日誌:

Process:   Python [905] 
Path:   /Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python 
Identifier:  Python 
Version:   2.7.7 (2.7.7) 
Code Type:  X86-64 (Native) 
Parent Process: bash [751] 
Responsible:  Terminal [410] 
User ID:   501 

Date/Time:  2014-07-09 22:31:43.221 +0800 
OS Version:  Mac OS X 10.9.3 (13D65) 
Report Version: 11 
.... 

.... 
Crashed Thread: 5 

Exception Type: EXC_CRASH (SIGABRT) 
Exception Codes: 0x0000000000000000, 0x0000000000000000 

Application Specific Information: 
abort() called 
*** error for object 0x100a4b600: pointer being freed was not allocated 
...... 
Thread 5 Crashed: 
0 libsystem_kernel.dylib   0x00007fff83153866 __pthread_kill + 10 
1 libsystem_pthread.dylib   0x00007fff8de8735c pthread_kill + 92 
2 libsystem_c.dylib    0x00007fff8ef88b1a abort + 125 
3 libsystem_malloc.dylib   0x00007fff8220707f free + 411 
4 libmysqlclient.18.dylib   0x0000000101027302 vio_delete + 44 
5 libmysqlclient.18.dylib   0x000000010100709a end_server + 48 
6 libmysqlclient.18.dylib   0x0000000101006f81 cli_safe_read + 49 
7 libmysqlclient.18.dylib   0x000000010100b469 cli_read_query_result + 26 
8 libmysqlclient.18.dylib   0x000000010100a648 mysql_real_query + 83 
9 _mysql.so      0x0000000100533be8 _mysql_ConnectionObject_query + 85 
10 org.python.python    0x00000001000c2fad PyEval_EvalFrameEx + 21405 
11 org.python.python    0x00000001000c3bfa PyEval_EvalFrameEx + 24554 
12 org.python.python    0x00000001000c3bfa PyEval_EvalFrameEx + 24554 
13 org.python.python    0x00000001000c4fb3 PyEval_EvalCodeEx + 2115 
14 org.python.python    0x00000001000c33f0 PyEval_EvalFrameEx + 22496 
15 org.python.python    0x00000001000c3bfa PyEval_EvalFrameEx + 24554 
16 org.python.python    0x00000001000c3bfa PyEval_EvalFrameEx + 24554 
17 org.python.python    0x00000001000c4fb3 PyEval_EvalCodeEx + 2115 
18 org.python.python    0x00000001000c33f0 PyEval_EvalFrameEx + 22496 
19 org.python.python    0x00000001000c3bfa PyEval_EvalFrameEx + 24554 
20 org.python.python    0x00000001000c3bfa PyEval_EvalFrameEx + 24554 
21 org.python.python    0x00000001000c3bfa PyEval_EvalFrameEx + 24554 
22 org.python.python    0x00000001000c4fb3 PyEval_EvalCodeEx + 2115 
23 org.python.python    0x000000010003eac0 function_call + 176 
24 org.python.python    0x000000010000ceb2 PyObject_Call + 98 
25 org.python.python    0x000000010001f56d instancemethod_call + 365 
26 org.python.python    0x000000010000ceb2 PyObject_Call + 98 
27 org.python.python    0x00000001000bc957 PyEval_CallObjectWithKeywords + 87 
28 org.python.python    0x0000000100102f27 t_bootstrap + 71 
29 libsystem_pthread.dylib   0x00007fff8de86899 _pthread_body + 138 
30 libsystem_pthread.dylib   0x00007fff8de8672a _pthread_start + 137 
31 libsystem_pthread.dylib   0x00007fff8de8afc9 thread_start + 13 

我跑了劇本與50個線程。發生的錯誤是間歇性的,但它是可重複的。我縮小了這個問題,這是由於插入/更新到MySQL。我讀到它可能是由於併發問題,但我如何解決它?

+0

Python代碼不應該轉儲核心。如果你遇到這樣的崩潰,這是MySQL綁定中的一個錯誤。一旦找到原因,你應該向MySQL-python人員提交一個bug。 – nmichaels

+0

tks快速回復。我將進一步調試在mysql – nuttynibbles

回答

2

我有同樣的問題,但我想過的方法不是多線程訪問數據庫。經過進一步的思考,我認爲有很多連接線程是不好的做法(或者至少它可能是棘手的業務)。想想如何進行批量讀取和寫入,並且在不涉及數據庫的情況下對處理進行多線程。

這仍然可能是在Python中的錯誤結合,但我可以通過簡化程序如何訪問數據庫和並行它真正需要進行並行代碼取得進展。希望這可以幫助!

+0

嗨,我同意你。事實上,我決定昨天就這樣做。現在我正在使用sqlalchemy,它添加了查詢buy,直到所有線程完成任務。有用!!! – nuttynibbles

+1

好主意!我只是累積行插入到列表,然後批量插入它們,但我更喜歡你的想法:) – rirwin

3

我在使用MySQLdb的OSX上遇到了相同的malloc錯誤。導致我錯誤的原因是在線程之間共享MySQLdb連接。使用每個線程的連接爲我固定它。

從文檔http://mysql-python.sourceforge.net/MySQLdb.html

MySQL協議可以用在一次相同的 連接不能處理多個線程。一些較早版本的MySQLdb利用鎖定 來實現2的線程安全性。雖然這並非難以通過使用標準光標類(它使用 mysql_store_result())完成,但它由SSCursor(其使用 mysql_use_result() ;後者則必須確保所有行可以執行另一個查詢之前 讀這是進一步 加入交易的複雜,因爲交易開始 當光標執行查詢,但到底什麼時候COMMIT或ROLLBACK是。 由Connection對象執行。兩個線程同時交易過程中根本無法共享 連接,除了不 能夠查詢EXEC期間分享ution。這太過於複雜的代碼,它只是不值得。

這樣做的一般結果是:不要共享 線程之間的連接。這真的不值得你的努力或地雷,並在年底, 可能會影響性能,因爲MySQL服務器運行一個單獨的線程 爲每個連接。您當然可以做一些事情,例如在池中緩存 連接,並在 時間將這些連接提供給一個線程。如果讓兩個線程同時使用一個連接時, MySQL客戶端庫可能會upchuck和死亡。你一直在 警告。

+0

是的,你是對的。每個線程的專用連接適用於我 – nuttynibbles

0

一般來說,這個錯誤可能是隨機的。我遇到了這個錯誤,但再次運行程序後沒有收到錯誤。我跑了我的程序(這與mysql_db無關,雖然也很複雜)5次。我只在第一次和第四次運行時發現了這個錯誤。

相關問題