c - 在 C 程序中处理 Sqlite3 CORRUPT 错误(11)的更好方法是什么?
问题描述
我看过很多关于Sqlite3 数据库磁盘映像在堆栈溢出中格式错误问题的文章。但我想知道如何处理 C 程序中的这个SQLITE_CORRUPT(错误代码:11)错误,当它发生在生产服务器期间时。
示例程序
#include <sqlite3.h>
#include <stdio.h>
int insert_records_to_database(sqlite3 *db)
{
char *err_msg = 0;
char *sql_in = "INSERT INTO Vehicles VALUES(1, 'maruthi', 5264);"
"INSERT INTO Vehicles VALUES(2, 'tesla', 5712);"
"INSERT INTO Vehicles VALUES(3, 'Skoda', 900);"
"INSERT INTO Vehicles VALUES(4, 'suzuki', 2900);"
"INSERT INTO Vehicles VALUES(5, 'ferrari', 35000);"
"INSERT INTO Vehicles VALUES(6, 'Citroen', 2100);"
"INSERT INTO Vehicles VALUES(7, 'honda', 4140);"
"INSERT INTO Vehicles VALUES(8, 'fiat', 2160);";
int rc = sqlite3_exec(db, sql_in, 0, 0, &err_msg);
if (rc != SQLITE_OK ) {
if(rc == SQLITE_CORRUPT)
{
printf(" SQLITE Database is corrupted :: How to handle");
}
fprintf(stderr, "SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return 1;
}
return 0;
}
int main(void) {
sqlite3 *db;
char *err_msg = 0;
int rc = sqlite3_open("/root/sqlite3/test.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
char *sql = "DROP TABLE IF EXISTS Vehicles;"
"CREATE TABLE Vehicles(Id INT, Name TEXT, Price INT);" ;
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
if (rc != SQLITE_OK ) {
fprintf(stderr, "SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return 1;
}
insert_records_to_database(db);
sqlite3_close(db);
return 0;
}
-> 在上述程序中,当发生此类错误时,我将退出程序。但仍然存在损坏的test.db,并且没有对 test.db 采取任何操作。假设,如果我想使用同一个数据库插入记录,最终会出现与磁盘映像格式错误相同的错误,它无法插入记录。
-> 当程序不断尝试将数据插入损坏的数据库时如何处理这种情况?是否有任何有效的方法来处理此类问题。
if (rc == SQLITE_CORRUPT)
{
printf(" SQLITE Database is corrupted :: How to handle");
}
我有解决方法:
删除 test.db(或)重新运行程序一次获得新创建的 test.db。
场景:如果程序无限循环运行,则在程序启动期间创建数据库(test.db)。之后,当程序每 15 分钟从内核接收数据,并在此期间将相同的数据插入到 sqlite3 中,如果发现损坏,则插入将失败。如何有效处理此案?
解决方案
对于您的场景:如果程序在无限循环中运行,则在程序启动期间创建数据库(test.db)。之后,当程序每 15 分钟从内核接收数据,并在此期间将相同的数据插入到 sqlite3 中,如果发现损坏,则插入将失败。如何有效处理此案?
设计您的代码如下:
解决方案1:
if (rc != SQLITE_OK ) {
if(rc == SQLITE_CORRUPT)
{
printf(" SQLITE Database is corrupted :: How to handle");
}
fprintf(stderr, "SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
# Remove the database file
remove("test.db");
# Then exit
exit(EXIT_FAILURE);
}
理想情况下,如果文件没有退出,您的应用程序应该创建新的 test.db。
解决方案2:
为应用程序的持续运行维护一个全局变量
global_variable =0
while(!global_variable) {
}
发生此错误时,请提高 SIGINT 以正常关闭您的应用程序。您需要有信号处理程序来捕获 SIGINT 并停止您的进程。
if (rc != SQLITE_OK ) {
if(rc == SQLITE_CORRUPT)
{
printf(" SQLITE Database is corrupted :: How to handle");
}
fprintf(stderr, "SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
# Remove the database file
remove("test.db");
# Raise SIGINT
raise(SIGINT);
}
# Register SIGINT
signal(SIGINT, signal_catchfunc);
void signal_catchfunc(int signal) {
global_variable=1
printf("!! signal caught !!\n");
}
推荐阅读
- matrix - 两个矩阵之间的相似性
- php - 如何隐藏添加到购物车按钮的特定角色和产品类别 Woocommerce
- python - 如何生成张量流矩阵,其中几列中的第一列为 1,其余列为 0
- node.js - 我看似有效的 URL 在本地解析,但在部署在 heroku 上时失败
- reactjs - 如何在反应中通过 id 设置值?
- python - 每当我尝试使用张量板时,我都没有找到模块错误
- python - Python中的正负正则表达式
- azure - NLog 与 Application Insights - 将异常记录为异常而不是跟踪
- javascript - Javascript输入键修复
- php - 需要关于 Laravel 的意见