并发Sqlite3:数据库表被锁定

时间:2016-02-17 16:16:20

标签: python sqlite python-3.4 pyzmq

我想在Python 3.4,SQLite3 v.3.8.11中生成以下设置:

(1)创建内存中共享缓存SQLite3数据库:

(2)创建一个仅从一个线程写入此DB的连接

(3)创建多个连接,从各个其他线程同时从此DB读取

这是我为测试这个而创建的:

import time
import zmq
import random
from threading import Thread
import sqlite3


def producer(context):
    zmq_socket = context.socket(zmq.PUB)
    zmq_socket.bind("inproc://test_pub")

    while True:
        msg = random.random()
        zmq_socket.send(str(msg).encode())
        wait_time = random.uniform(0, 0.05)
        time.sleep(wait_time)



def subscriber_writer(context):

    # Create database connection for writing to memory
    write_con = sqlite3.connect('file::memory:?cache=shared', uri=True)
    cursor = write_con.cursor()

    zmq_socket = context.socket(zmq.SUB)
    zmq_socket.connect("inproc://test_pub")
    zmq_socket.setsockopt(zmq.SUBSCRIBE, b'')

    while True:
        msg = float(zmq_socket.recv().decode())
        cursor.execute('UPDATE TEST SET Value=? WHERE Key="Val"', [msg])
        write_con.commit()


def consumer(context):

    # Create database connection for reading from memory in read-only mode
    read_con = sqlite3.connect('file::memory:?cache=shared&mode=ro', uri=True)
    cursor = read_con.cursor()

    while True:
        cursor.execute('SELECT Value FROM TEST WHERE Key="Val"')
        row = cursor.fetchone()
        result = row[0]
        print(str(result))
        wait_time = random.uniform(0, 0.05)
        time.sleep(wait_time)


def main():

    # Create context
    context = zmq.Context()

    # Create database
    con = sqlite3.connect('file::memory:?cache=shared', uri=True)

    # Create db table
    cursor = con.cursor()
    cursor.execute('CREATE TABLE TEST(Key TEXT, Value NUMERIC)')
    cursor.execute('INSERT INTO TEST VALUES (?,?)', ["Val", 0.00])
    con.commit()

    Thread(target=subscriber_writer, args=(context,)).start()
    Thread(target=producer, args=(context,)).start()
    Thread(target=consumer, args=(context,)).start()

if __name__ == '__main__':
    main()

这有效一段时间.....但后来我收到以下错误:

...
0.2504188310554989
0.2504188310554989
0.8038719720740617
0.42408896748682956
0.21361498908206744
0.3404497358396832
0.010459475861968603
0.5070540941748318
0.5070540941748318
0.23151535812095037
0.636881359928549
0.4184038089576615
0.9920311052908629
Exception in thread Thread-3:
Traceback (most recent call last):
  File "E:\Python34-64\lib\threading.py", line 911, in _bootstrap_inner
    self.run()
  File "E:\Python34-64\lib\threading.py", line 859, in run
    self._target(*self._args, **self._kwargs)
  File "test.py", line 43, in consumer
    cursor.execute('SELECT Value FROM TEST WHERE Key="Val"')
sqlite3.OperationalError: database table is locked: TEST

我该如何使用?

作为附注,仅与 check_same_thread=False建立联系,并在整个过程中分享这一点,即使等待时间被消除也是如此.... 这是可取的改为?见下文:

import time
import zmq
import random
from threading import Thread
import sqlite3


def producer(context):
    zmq_socket = context.socket(zmq.PUB)
    zmq_socket.bind("inproc://test_pub")

    while True:
        msg = random.random()
        zmq_socket.send(str(msg).encode())
        # wait_time = random.uniform(0, 0.05)
        # time.sleep(wait_time)



def subscriber_writer(context, con):

    zmq_socket = context.socket(zmq.SUB)
    zmq_socket.connect("inproc://test_pub")
    zmq_socket.setsockopt(zmq.SUBSCRIBE, b'')

    cursor = con.cursor()

    while True:
        msg = float(zmq_socket.recv().decode())
        cursor.execute('UPDATE TEST SET Value=? WHERE Key="Val"', [msg])


def consumer(context, con):

    cursor = con.cursor()

    while True:
        cursor.execute('SELECT Value FROM TEST WHERE Key="Val"')
        row = cursor.fetchone()
        result = row[0]
        print(str(result))
        # wait_time = random.uniform(0, 0.05)
        # time.sleep(wait_time)


def main():

    # Create context
    context = zmq.Context()

    # Create database
    con = sqlite3.connect('file::memory:?cache=shared', uri=True, isolation_level=None, check_same_thread=False)

    # Create db table
    cursor = con.cursor()
    cursor.execute('CREATE TABLE TEST(Key TEXT, Value NUMERIC)')
    cursor.execute('INSERT INTO TEST VALUES (?,?)', ["Val", 0.00])

    Thread(target=subscriber_writer, args=(context, con)).start()
    Thread(target=producer, args=(context,)).start()
    Thread(target=consumer, args=(context, con)).start()

if __name__ == '__main__':
    main()

0 个答案:

没有答案
相关问题