Помогите, пожалуйста, решить следующую проблему.
Нужно записывать данные в PostgresQL одновременно в нескольких потоках, используя одно и то же соединение (т.к. потоков очень много, и если каждый будет открывать свое соединение, получится существенное замедление работы).
Вот такой скрипт набросал:
global conn
ips = []
ips = GetIp() #код это функции приводить не буду, она просто достает данные из БД
for ip in ips:
dbt = DBThread(ip)
dbt.start()
while threading.activeCount() > 1: time.sleep(1)
conn.close()
class DBThread(threading.Thread):
def __init__(self, ip):
self.ip = ip
threading.Thread.__init__(self)
self.cur = conn.cursor()
self.cpy = StringIO()
def run(self):
#здесь идет блок кода, формирующий строку для всавки в БД методом COPY,
#условно обозначу его
str_for_copy = get_str()
self.cpy.write(str_for_copy)
self.cpy.seek(0)
self.cur.copy_from(self.cpy, 'my_table', columns = ('column1', 'column2'))
conn.commit()
Если потоков немного, порядка 5, то все отрабатывает на ура. При сотне-другой после нескольких успешных записей валится ошибка:
Exception in thread Thread-19:
Traceback (most recent call last):
File "/usr/local/lib/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "/path/script.py", line 91, in run
cur.copy_from(cpy, 'my_table', columns = ('column1', 'column2'))
DatabaseError: no COPY in progress
Exception in thread Thread-218:
Traceback (most recent call last):
File "/usr/local/lib/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "/path/script.py", line 57, in run
rows = cur.fetchall() #это первая строка в методе, использующая cur
InterfaceError: cursor already closed
Ощущение, как будто потоки не успевают освобождать какой-то общий ресурс.
То ли фича питона такая, то ли я где недопонимаю.