C++ SQLite 序列化模式问题
C++ SQLite Serialized Mode Questions
我已经浏览了好几页,并且对它所想的事情有了一个很好的了解,但我有几个问题只是为了确定....
我的程序使用 -DTHREADSAFE=1 编译选项,在收到来自用户或我的网络的数据库请求(Select、删除、插入、更新)时分叉,然后是 child 进程处理各种数据库任务,并在需要时中继消息等等,
目前我的数据库没有为并发设置,我不会撒谎这是一个主要的设计缺陷,但这不是重点,假设我有一个函数可以打印我 [=64 中的所有条目=] 分类帐如下...
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!");
}
- my setupOutput(), printlnEnd(), println(), 都对我使用 'non-blocking' 键盘 i/o 有帮助,它们按我想要的方式工作让我们在这里不用担心它们,想想其中只是对 cout
的调用
好的,现在我认为有 4 个选项...
在我的 try/catch 周围待一会儿,然后在 catch 中检查是否 err = 5,如果是这样我需要设置一个 sqlite3_busy_handler 并让它等待任何阻塞当前操作(一旦它 returns SQLITE_OK 并清理了我再次通过 while/try 重申的所有旧变量),现在一次只能设置其中一个,让我们举例来说,Child1 正在进行大量写入,而 child2 和 child3 正试图在第一个 child 的写入之上同时读取和更新,因此如果 SQLITE_BUSY 被这个函数 return 打印出一个错误,然后重新启动我的 while 循环(重新启动函数),当然是在我完成旧语句并清除任何本地 objects 之后如果这是正确的思路,可能已经创建了?
我是否应该设置一个递归互斥锁,比如将其固定到 SQLites 自己的锁定机制中,将其设置为跨进程共享,然后一次只允许对数据库执行一项操作?对于小规模使用我的应用程序来说,这似乎是一个不错的选择,但是我正在阅读很多关于使用递归互斥体的警告,我想知道这是否是最好的选择,因为许多帖子都说 handle mutual排除自己。但是我不能并发读取,这有点痛苦
使用选项 1 但不使用 SQLite 繁忙处理程序,只需对随机数调用 usleep,清理数据,然后重新启动 while?
before/after 涉及我的数据库的任何函数分别使用 sqlite3_exec() 和 "BEGIN IMMEDIATE"/"COMMIT",在这两个语句之间的代码。因此,没有任何内容可以(或至少应该)return SQLITE_BUSY,然后如果我的 "BEGIN IMMEDIATE" returns BUSY(它应该是唯一的,只要一切都是设置正确),我使用 sqlite3_busy_handler 老实说,如果一次只有一个进程可以使用它似乎很烦人......或者一个带有 usleep() 的随机数,(大概这个数字相当大 1mil = 1 秒 1-20 个进程之间重叠的机会非常小)因此每个进程都会根据自己的目的不断尝试以随机间隔重新锁定数据库
有没有更好的方法?或者其中哪一个最好?
SQLite 的内部繁忙处理程序(与 sqlite3_busy_timeout() 一起安装)已经睡眠了或多或少的随机次数;无需编写自己的处理程序。
使用你自己的锁定机制比随机等待更有效,但前提是你有 reader/writer 个锁。
BEGIN 或 BEGIN IMMEDIATE 确保同一事务中没有其他语句可以 运行 锁定,但前提是 IMMEDIATE 用于写入的事务。
要允许并发读取器和写入器,请考虑使用 WAL mode。 (但这也不允许多个作者。)
我已经浏览了好几页,并且对它所想的事情有了一个很好的了解,但我有几个问题只是为了确定....
我的程序使用 -DTHREADSAFE=1 编译选项,在收到来自用户或我的网络的数据库请求(Select、删除、插入、更新)时分叉,然后是 child 进程处理各种数据库任务,并在需要时中继消息等等,
目前我的数据库没有为并发设置,我不会撒谎这是一个主要的设计缺陷,但这不是重点,假设我有一个函数可以打印我 [=64 中的所有条目=] 分类帐如下...
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!");
}
- my setupOutput(), printlnEnd(), println(), 都对我使用 'non-blocking' 键盘 i/o 有帮助,它们按我想要的方式工作让我们在这里不用担心它们,想想其中只是对 cout 的调用
好的,现在我认为有 4 个选项...
在我的 try/catch 周围待一会儿,然后在 catch 中检查是否 err = 5,如果是这样我需要设置一个 sqlite3_busy_handler 并让它等待任何阻塞当前操作(一旦它 returns SQLITE_OK 并清理了我再次通过 while/try 重申的所有旧变量),现在一次只能设置其中一个,让我们举例来说,Child1 正在进行大量写入,而 child2 和 child3 正试图在第一个 child 的写入之上同时读取和更新,因此如果 SQLITE_BUSY 被这个函数 return 打印出一个错误,然后重新启动我的 while 循环(重新启动函数),当然是在我完成旧语句并清除任何本地 objects 之后如果这是正确的思路,可能已经创建了?
我是否应该设置一个递归互斥锁,比如将其固定到 SQLites 自己的锁定机制中,将其设置为跨进程共享,然后一次只允许对数据库执行一项操作?对于小规模使用我的应用程序来说,这似乎是一个不错的选择,但是我正在阅读很多关于使用递归互斥体的警告,我想知道这是否是最好的选择,因为许多帖子都说 handle mutual排除自己。但是我不能并发读取,这有点痛苦
使用选项 1 但不使用 SQLite 繁忙处理程序,只需对随机数调用 usleep,清理数据,然后重新启动 while?
before/after 涉及我的数据库的任何函数分别使用 sqlite3_exec() 和 "BEGIN IMMEDIATE"/"COMMIT",在这两个语句之间的代码。因此,没有任何内容可以(或至少应该)return SQLITE_BUSY,然后如果我的 "BEGIN IMMEDIATE" returns BUSY(它应该是唯一的,只要一切都是设置正确),我使用 sqlite3_busy_handler 老实说,如果一次只有一个进程可以使用它似乎很烦人......或者一个带有 usleep() 的随机数,(大概这个数字相当大 1mil = 1 秒 1-20 个进程之间重叠的机会非常小)因此每个进程都会根据自己的目的不断尝试以随机间隔重新锁定数据库
有没有更好的方法?或者其中哪一个最好?
SQLite 的内部繁忙处理程序(与 sqlite3_busy_timeout() 一起安装)已经睡眠了或多或少的随机次数;无需编写自己的处理程序。
使用你自己的锁定机制比随机等待更有效,但前提是你有 reader/writer 个锁。
BEGIN 或 BEGIN IMMEDIATE 确保同一事务中没有其他语句可以 运行 锁定,但前提是 IMMEDIATE 用于写入的事务。
要允许并发读取器和写入器,请考虑使用 WAL mode。 (但这也不允许多个作者。)