【发布时间】:2020-01-10 03:52:12
【问题描述】:
我有一个服务器/客户端程序,服务器为每个连接的客户端生成一个带有 fork() 的子程序。然后,客户端向服务器发送命令以在 sqlite3 数据库上执行某些查询(INSERT INTO、SELECT、DELETE FROM)。
注意:我在 fork() 之后打开数据库,如下所示:@ 987654321@ 2.6
问题
当 1 个客户端连接时完美运行,但当有 2 个客户端连接时:当其中一个执行修改数据库的第一个查询(例如:INSERT INTO)时,从那时起只有它可以继续修改。其余的得到错误:数据库已锁定。即使在阻塞.db的客户端终止后,对方仍然无法修改。
我试过了:
- PRAGMA journal_mode=wal 在 sqlite3 终端中
- 手动执行BEGIN TRANSACTION;在INSERT查询之前和COMMIT;之后
- sqlite3_close(db) 在 INSERT 查询之后并在之后重新打开它
观察:
我知道使用线程可能会更安全并且可以解决问题,但我想在更改整个项目结构之前尝试使用 fork() 进行所有操作。
服务器代码(我删除了不相关的代码部分):
int main () {
sqlite3* db;
//code for connection...
while (1) {
client = accept(sd, (struct sockaddr *) &from, &length);
if (-1 == (pid = fork())) {
perror("Error at fork");
}
if (pid == 0) {
if (sqlite3_open("./Database.db", &db))
perror("Error: Could not open database.\n")
while (1) {
sprintf(query, "INSERT INTO table VALUES ('%s','%s','%s','%s','%s','%s');",string1, string2,string3,string4,string5,string6);
if(sqlite3_exec(db, query, NULL, 0, &error) != SQLITE_OK){
printf("%s", sqlite3_errmsg(db));
fflush(stdout);
}
}
}
感谢您的宝贵时间!
【问题讨论】:
-
perror不合适。如果sqlite_open3返回的不是SQLITE_OK,则可以从sqlite3_errmsg获得正确的错误信息。那么,您实际上遇到了什么错误? -
没错,我会解决这个问题,但数据库会正确打开,因为查询可以在我提出的情况之外正常执行
-
啊,你是说
exec失败了? -
您确实应该使用prepared statement 并将要插入的值绑定到其中的参数,而不是使用
sprintf()构建字符串并使用sqlite3_exec()。这就是你如何获得 sql 注入攻击、神秘的语法错误等。 -
是的,printf("%s", sqlite3_errmsg(db)) 打印错误数据库已锁定。
标签: c database sqlite fork blocked