LINUX.ORG.RU

запись в sqlite базу из многопоточного приложения

 ,


1

0

есть многопоточное приложение. оно пишет в sqlite базу. Здесь нет ничего сложного, так как sqlite поддерживает multiple connections. Но есть одно но. часто после вставки нужно взять last inserted id.

подскажите алгоритм, наиболее подходящий для данной задачи. пока что склоняюсь к этому

если это имеет значение - использую ruby

★★★★★

Последнее исправление: ZuBB (всего исправлений: 2)

Ответ на: комментарий от baverman

И ты, конечно же, не менял ни одной строчки кода?

нет - я тебе доверяю, беру твой вариант и запускаю, не стоит?

wota ★★
()
Ответ на: комментарий от baverman

подтверждаю

Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "t.py", line 26, in writer
    cursor.execute('INSERT INTO boo(title) VALUES (?)', ('boo',))
OperationalError: database is locked

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "t.py", line 26, in writer
    cursor.execute('INSERT INTO boo(title) VALUES (?)', ('boo',))
OperationalError: database is locked

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "t.py", line 26, in writer
    cursor.execute('INSERT INTO boo(title) VALUES (?)', ('boo',))
OperationalError: database is locked
$ python --version
Python 2.7.3
anonymous
()
Ответ на: комментарий от note173

Безопаснее всего выделить один поток под базу и отправлять ему задачи, когда нужно что-то узнать после вставки, — блокирующие.

плюсую дважды. Чуть только перефразирую - под storage выделять отдельную сучность, в многопоточном приложении - нить или их пул под общим интерфейсом. В реальном проекте был sqlite, реализован интерфейс под бизнес-логику на пуле. Конкурентная модель - один писатель, много читателей.

Итог - усё работает :) В жизненном цикле была миграция на постгресс (веяния чрезчур прогрессивных топ-менеджерей) и обратно (ибо реальность)

MKuznetsov ★★★★★
()
Ответ на: комментарий от wota

вот вариант для файла, ну и таки честные потоки, а не все в одном ;)

#include <csignal>
#include <set>
#include <sqlite3.h>
#include <thread>
#include <vector>
using namespace std;

int main() 
{
    sqlite3* db;
    sqlite3_open_v2( "/tmp/boo.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0 );
    sqlite3_exec( db, "PRAGMA journal_mode=OFF", 0, 0, 0 );
    sqlite3_exec( db, "PRAGMA synchronous=0", 0, 0, 0 );
    sqlite3_exec( db, "CREATE TABLE boo( id INTEGER PRIMARY KEY AUTOINCREMENT, title text)", 0, 0, 0 );

    set<int> ids;
    thread ths[ 4 ];
    
    for( size_t i = 0 ; i < 4 ; ++i )
        ths[ i ] = thread( [db,&ids] {
            for( size_t j = 0 ; j < 10000 ; ++j )
            {
                sqlite3_mutex_enter( sqlite3_db_mutex(db) );
                sqlite3_exec( db, "INSERT INTO boo(title) VALUES ('boo')", 0, 0, 0 );
                if( !ids.insert( sqlite3_last_insert_rowid(db) ).second ) raise( SIGTRAP );
                sqlite3_mutex_leave( sqlite3_db_mutex(db) );
            }
        } );
        
    for( auto& th : ths )
        th.join();
    
    sqlite3_close( db );
}
wota ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.