
用得是自带的 sqlite3 库,可能有 100 个左右的线程吧,目前是每个线程拥有一个单独的连接,所有连接的插入间隔大约是 0.00x 秒,会出现 datebase is locked 错误,请问怎么处理呢?
1 mansur 2017-01-18 22:32:31 +08:00 弄一个队列写吧 |
2 murmur 2017-01-18 22:55:55 +08:00 我怎么印象中 sqlite 用排队+锁的机制比多线程还要好一点 100 线程的话为啥不考虑 mysql 啊 |
3 hosiet 2017-01-18 22:57:40 +08:00 via Android 写入发现被锁了就循环多试几次嘛,可以给个重试上限(例如五次,或者没上限也行)以及重试时间间隔等等。 不过我记得好像有阻塞的写法吧,就是完成写入才返回那种。不知道你用的是什么编程语言? |
6 hosiet 2017-01-18 23:02:18 +08:00 via Android 糟糕没看节点( Python )。 pysqlite 不支持多线程共享连接是个问题。 |
7 clino 2017-01-18 23:07:57 +08:00 via Android gevent 并发,这样同时只有一个读写 sqlite |
9 zwh8800 2017-01-19 10:56:43 +08:00 sqlite 并发不行的, sqlite 的事务就是锁表,你无论开几个线程,只要访问的是同一张表,最后在 sqlite 那里都会被锁,实际上最后都是顺序执行的。 正解是队列 <del>更正确的解是换数据库</del> @hosiet 重试一方面不优雅,另一方面会让性能更糟糕,堆积的重试操作多了之后,大家都抢不到锁。 |
10 tomwei7 2017-01-19 11:36:47 +08:00 加个队列吧, sqlite 不适合高并发的 |
11 gdsagdada 2017-01-19 11:50:02 +08:00 # coding:utf-8 import sqlite3 import queue, os def singleton(cls): instances = {} def _singleton(*args, **kw): if cls not in instances: instances[cls] = cls(*args, **kw) return instances[cls] return _singleton @singleton class SQLiteUtil(object): __queue_cOnn= queue.Queue(maxsize=1) __path = None def __init__(self, path): self.__path = path print('path:', self.__path) self.__create_conn() def __create_conn(self): cOnn= sqlite3.connect(self.__path, check_same_thread=False) self.__queue_conn.put(conn) def __close(self, cursor, conn): if cursor is not None: cursor.close() if conn is not None: cursor.close() self.__create_conn() def execute_query(self, sql, params): cOnn= self.__queue_conn.get() cursor = conn.cursor() value = None try: records = None if not params is None: records = cursor.execute(sql, params).fetchall() else: records = cursor.execute(sql).fetchall() field = [i[0] for i in cursor.description] value = [dict(zip(field, i)) for i in records] finally: self.__close(cursor, conn) return value def executescript(self, sql): cOnn= self.__queue_conn.get() cursor = conn.cursor() try: cursor.executescript(sql) conn.commit() except Exception as e: conn.rollback() raise finally: self.__close(cursor, conn) def execute_update(self, sql, params): return self.execute_update_many([sql], [params]) def execute_update_many(self, sql_list, params_list): cOnn= self.__queue_conn.get() cursor = conn.cursor() count = 0 try: for index in range(len(sql_list)): sql = sql_list[index] params = params_list[index] if not params is None: count += cursor.execute(sql, params).rowcount else: count += cursor.execute(sql).rowcount conn.commit() except Exception as e: conn.rollback() raise finally: self.__close(cursor, conn) return count ''' example: One= SQLiteUtil('xxx.sqlite') rst = one.execute_query('select * from website', None) for line in rst: print(line.get('id'), line.get('url'), line.get('content')) print(one.execute_update('update website set cOntent= \'2222222\' where id = ?', ('1',))) print(one.execute_update('update website set cOntent= \'2222222\' where id = \'1\'', None)) print('update many') count = one.execute_update_many( [ 'update website set cOntent= \'一\' where id = \'1\'', 'update website set cOntent= \'二\' where id = \'2\'', 'update website set cOntent= 1 where id = \'3\'' ], [None, None, None] ) print('count:', count) ''' python3 的 用 py2 自己改改,可抗千万级并发[v2ex 滑稽专属表情] |
12 gdsagdada 2017-01-19 11:52:15 +08:00 楼主改 py2 了记得也贴下 |
13 Actrace 2017-01-19 13:21:28 +08:00 sqlite 是针对小型的移动设备设计的数据库。。。楼主这是准备拿 100 台手机来做服务器集群吗。。 |
14 thekoc OP |
17 gdsagdada 2017-01-19 17:06:55 +08:00 把你程序也贴出来大家观赏下[v2ex 滑稽] |