【发布时间】:2016-07-12 20:35:26
【问题描述】:
我已经浏览了相当多的页面,并且对它的想法有一个很好的想法,但我有几个问题只是为了确定......
我的程序使用 -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(),所有这些都有助于我使用“非阻塞”键盘输入/输出,它们可以按我的意愿工作,在这里不用担心它们,把它们想象成打电话给 cout
好的,所以现在我认为有 4 个选项...
在我的 try/catch 附近,然后在 catch 检查 err = 5,如果是,我需要设置一个 sqlite3_busy_handler 并让它等待任何阻塞当前操作的东西(一旦它返回 SQLITE_OK 并已清理把我所有的旧变量都重复一遍/再试一次),现在因为一次只能设置其中一个,比如说 Child1 正在做一个大写,而 child2 和 child3 正试图同时说读取和更新在第一个孩子的写入之上,所以如果这个函数返回一个 SQLITE_BUSY 我打印出一个错误,然后重新启动我的 while 循环(重新启动函数),当然在我完成了我的旧语句并清除了任何本地对象之后如果这是正确的思路,可能已经创建了?
我是否应该设置一个递归互斥锁,比如将其拧到 SQLite 自己的锁定机制上,将其设置为跨进程共享,然后一次只允许对数据库进行一项操作?对于在小范围内使用我的应用程序,这似乎不是一个坏的选择,但是我正在阅读很多关于使用递归互斥锁的警告,并且想知道这是否是最好的选择,因为许多帖子都说处理相互排斥自己。但是我不能同时读取,这有点痛苦
使用选项 1,但不使用 SQLite 繁忙处理程序,只需对随机数调用 usleep,清理数据,然后重新启动?
在涉及我的数据库的任何函数之前/之后分别使用带有“BEGIN IMMEDIATE”/“COMMIT”的 sqlite3_exec(),在这两个语句之间的代码持续时间内锁定数据库。因此,任何包含在里面的东西都不能(或至少应该)返回 SQLITE_BUSY,然后如果我的“BEGIN IMMEDIATE”返回 BUSY(只要一切设置正确,它应该是唯一的),我使用 sqlite3_busy_handler 老实说,如果只是一个进程一次可以使用它似乎很烦人......或者使用 usleep() 的随机数,(大概在这个数字相当大 1mil = 1 秒时,1-20 个进程之间重叠的机会非常小)所以每个进程会为了自己的目的不断尝试以随机间隔重新锁定数据库
有没有更好的方法?或者其中哪一个是最好的?
【问题讨论】:
标签: c++ multithreading sqlite mutex