Python与多个线程共享数据库连接

时间:2017-01-13 08:40:05

标签: python multithreading threadpool mysql-python python-multithreading

我正在创建一个数据库连接,我在多个线程(大约100到1000个线程)之间共享它,我收到如下错误,

  

1)我的代码出了什么问题?

这是我的示例代码,我将在以下场景中更改此代码: 根据一些SQL结果,它将创建最多1000个线程。 如果我为每个线程创建数据库连接,它将创建更多的数据库连接。为了避免这种情况,我在所有线程中使用了相同的数据库连接,我只进行了插入和更新操作。

  

2)这种多线程是否有更好的方法   情景?

错误:

Worker: 0
Create Notification called for userid abcxyz and message is Test Message : Worker: 0 Attempt: 0
Sleeping ... 

Worker: 1
Create Notification called for userid abcxyz and message is Test Message : Worker: 1 Attempt: 0

Partial insertedID 43
Traceback (most recent call last):
  File "T:\work\Testing\src\notification_data_feeder.py", line 58, in createNotification
    db.commit()
OperationalError: (2006, 'MySQL server has gone away')

Error on createNotification 
Traceback (most recent call last):
  File "T:\work\Testing\src\notification_data_feeder.py", line 54, in createNotification
    cursor.execute("INSERT INTO push_notification_data (user_id, trig_time, msg, msg_prio, type, trig_ref, lang) VALUES (%s, %s, %s, %s, %s, %s, %s)", (str(userid), current_gmt_datetime, msg, msgPriority, '2', trigRef, lang))
  File "N:\Installation\Python27\lib\site-packages\MySQLdb\cursors.py", line 174, in execute
    self.errorhandler(self, exc, value)
  File "N:\Installation\Python27\lib\site-packages\MySQLdb\connections.py", line 36, in defaulterrorhandler
    raise errorclass, errorvalue
OperationalError: (2013, 'Lost connection to MySQL server during query')

Error on createNotification

代码:

import json
import os
from random import randint
import threading
from time import sleep
import time, datetime
from urllib2 import Request, urlopen, HTTPError
import traceback
import MySQLdb
import socket
from collections import defaultdict

import CONST_LOCAL
from Notification import Notification
from Notification import UserDevice

def convertQueryResultToDevices(userDevicesRows, cursor): 
    userDevices = []
    if userDevicesRows is not None:
        for userDevicesRow in userDevicesRows:
            userDevice = UserDevice()
            userDevice.userId = userDevicesRow[0]
            userDevice.deviceId = userDevicesRow[1]
            userDevice.deviceType = userDevicesRow[2]
            userDevices.append(userDevice);
    return userDevices;  

def getDeviceIdsByUser(userId, cursor):
    userDevices = None;
    try :
        cursor.execute("SELECT uuid, registration_id, device_type  FROM userid_data WHERE userid = %s", (userId));
        userDevicesRows = cursor.fetchall()
        # Convert SQL Row to model object
        userDevices = convertQueryResultToDevices(userDevicesRows, cursor)   
    except:
        print(traceback.format_exc())

    return userDevices;

def createNotification(userid, msg, msgPriority, type, trigRef, lang, db, cursor):
    print("Create Notification called for userid " + str(userid) + " and message is " + msg)    
    try:
        # Insert the notification message
        current_gmt_datetime = datetime.datetime.fromtimestamp(time.mktime(time.gmtime()));
        cursor.execute("INSERT INTO notification_data (user_id, triger_time, msg, msg_prio, type, trig_ref, lang) VALUES (%s, %s, %s, %s, %s, %s, %s)", (str(userid), current_gmt_datetime, msg, msgPriority, '2', trigRef, lang))

        insertedID = cursor.lastrowid
        print("Partial insertedID " + str(insertedID))

        # Commit this insertion
        if db:
            db.commit()

        # Get Devices of the user
        userDevices = getDeviceIdsByUser(userid, cursor)
        if userDevices is not None:
            for userDevice in userDevices:
                deviceId = userDevice.deviceId
                deviceType = userDevice.deviceType
                # If the value exists
                if deviceId:
                    # Default value
                    deviceTypeInt = 1;

                    cursor.execute("INSERT INTO notification_status (notification_id, device_id, device_type, status, attempts, delivery_status, delivery_err_reason) VALUES (%s, %s, %s, %s, %s, %s, %s)", (insertedID, deviceId, deviceTypeInt, 0, 0, 0, 0))

            # Commit this status row of the previous inserted data row
            if db:
                db.commit()

        print("Notification created , notification id " + str(insertedID))  
    except MySQLdb.Error, e:
        print(traceback.format_exc())
        print("Error on createNotification ")

def worker(num, attempt, db, cursor):
    """thread worker function"""
    for i in range(attempt):
        print 'Worker: %s' % num
        message = "Test Message : Worker: " + str(num) + " Attempt: " + str(i)
        createNotification("abcxyz", message, 1, 1, 1, 1, db, cursor)
        # Sleep for testing purpose
        sleep(1)

if __name__ == '__main__':
    threads = []
    attempt = 1

    try:
        # Create DB connection, It will be shared across all threads
        db = MySQLdb.connect(CONST_LOCAL.DATABASE_SERVER, CONST_LOCAL.DATABASE_USER, CONST_LOCAL.DATABASE_PASSWORD, CONST_LOCAL.DATABASE_NAME)
        cursor = db.cursor()

        # Create Two threads, Each thread will insert one entry
        for i in range(2):
            t = threading.Thread(target=worker, args=(i, attempt, db, cursor))
            threads.append(t)
            t.start()
    except:
        print(traceback.format_exc())

    print("Sleeping ... ")
    # Testing purpose
    sleep(50000)
    print("Completed ... ")

0 个答案:

没有答案