C ++ SQLite序列化模式问题

时间:2016-03-25 04:25:43

标签: c++ multithreading sqlite mutex

我已经阅读了几页,并且有一个很好的想法,它想到了什么,但我有几个问题只是为了确定....

我的程序使用-DTHREADSAFE = 1编译选项,在从用户或我的网络接收数据库请求(选择,删除,插入,更新)时分叉,然后子进程处理各种数据库任务和消息中继如果需要等等,

目前我的数据库没有设置为并发,我不会说谎是一个主要的设计缺陷,但是现在除了这一点之外,让我们说我有一个打印所有的功能我的表格LEDGER中的条目如下......

void PersonalDataBase::printAllEntries()
{
//get all entries
const char query [] = "select * from LEDGER";
sqlite3_stmt *stmt;
int error

try
{
    if ((error = sqlite3_prepare(publicDB, query, -1, &stmt, 0 )) == SQLITE_OK)
    {
        int ctotal = sqlite3_column_count(stmt);
        int res = 0;

        while ( 1 )         
        {
                res = sqlite3_step(stmt);

                if ( res == SQLITE_ROW ) 
                {
                    Entry *temp = loadBlockRow(stmt);

                    string from, to;
                    from = getNameForHash(temp -> from);
                    to = getNameForHash(temp -> to);

                    temp -> setFromOrTo(from, 0);
                    temp -> setFromOrTo(to, 1);

                    temp -> printEntry();
                    printlnEnd();
                    delete temp;
                }
                else if ( res == SQLITE_DONE || res==SQLITE_ERROR)    
                {
                    if (res == SQLITE_ERROR) { throw res; }
                    sqlite3_finalize(stmt);
                    break;
                }    
        }
    }
    //problems
    else
    {
        throw error;
    }
}
catch (int err)
{
    sqlite3_finalize(stmt);
    setupOutput();
    cout << "Database Error: " << sqlite3_errmsg(publicDB) << ", Error Code: " << (int) error << endl;
    cout << "Did Not Find Values Try Again After Fixing Problems Above." << endl;   
    printlnEnd();
}
println("Done!");
}
  • 我的setupOutput(),printlnEnd(),println(),帮助我使用&#39;非阻塞&#39;键盘输入/输出,他们按照我想要的方式工作,不要在这里担心,并将它们视为对cout的调用

好的,所以现在我觉得有4种选择......

  1. 在我的try / catch周围,然后在catch检查err = 5,如果是这样的话,我需要设置一个sqlite3_busy_handler并等待阻止当前操作的任何东西(一旦它返回SQLITE_OK并且已经清理过)通过while / try再次重申我所有的旧变量,现在因为其中只有一个可以一次设置,让我们说例如Child1正在进行大写,而child2和child3正试图说在第一个孩子的写入之上同时读取和更新,所以如果这个函数返回一个SQLITE_BUSY,我打印出一个错误,然后重启我的while循环(重启函数),当然我已经完成了我的旧语句,并清除可能已创建的任何本地对象,如果这是正确的思路?

  2. 我应该设置一个递归的互斥锁,比如把它拧成SQLites自己的锁定机制,把它设置为跨进程共享,然后一次只允许对数据库进行一次操作?为了小规模地使用我的应用程序这似乎不是一个选项,但是我在阅读使用递归互斥锁的很多警告时我想知道这是否是最好的选择,就像许多选项一样帖子说自己处理互斥。然而,我不能同时阅读,这有点痛苦

  3. 使用选项1,而不是使用SQLite忙处理程序,只需在随机数上调用usleep,清理数据,然后重新启动?

  4. 在涉及我的数据库的任何函数之前/之后使用sqlite3_exec()和&#34; BEGIN IMMEDIATE&#34; /&#34; COMMIT&#34;分别在这两个语句之间锁定数据库的持续时间。因此,包含在其中的任何内容都不能(或者至少应该)返回SQLITE_BUSY,那么如果我的&#34; BEGIN IMMEDIATE&#34;返回BUSY(它应该是唯一的一个,只要一切设置正确),我使用sqlite3_busy_handler,老实说,如果只有一个进程可以一次使用它似乎很烦人...或者随机数字与usleep(), (可能在这个数字相当大1mil = 1秒时,1-20个进程之间重叠的可能性非常小)所以每个进程都会不断尝试以随机的间隔重新锁定数据库以用于自己的目的

  5. 有更好的方法吗?或哪一个最好?

1 个答案:

答案 0 :(得分:0)

SQLite的内部繁忙处理程序(与sqlite3_busy_timeout()一起安装)已经或多或少地随机休眠;没有必要编写自己的处理程序。

使用自己的锁定机制比随机等待更有效,但前提是你有读写器锁定。

BEGIN或BEGIN IMMEDIATE确保同一事务中的其他语句不能进入锁定,但仅当IMMEDIATE用于写入的事务时才会生效。

要允许并发读者和作者,请考虑使用WAL mode。 (但这也不允许多个作者。)