[英]SQLite transaction on power failure or system crash
我有一個正在運行的 C 程序更新 SQLite 記錄的描述,我希望它是事務性的,這就是為什么在執行 UPDATE 語句之前和之后有 BEGIN 和 COMMIT 語句的原因。 如果我的 SQLite 數據庫系統遇到電源故障、斷電或操作系統崩潰,我不確定這是否已經足夠? 謝謝!
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
int
main(void)
{
sqlite3 *db_ptr;
sqlite3_stmt *stmt0, *stmt1, *stmt2;
char desc[25];
int ret = 0;
ret = sqlite3_open("stock.db", &db_ptr);
if (ret != SQLITE_OK) {
printf("Database opening error\n");
}
printf("Modify description: ");
gets_s(desc, 24);
char sql_stmt0[128];
strlcpy(sql_stmt0, "BEGIN TRANSACTION", sizeof(sql_stmt0));
strlcat(sql_stmt0, ";", sizeof(sql_stmt0));
ret = sqlite3_prepare_v2(db_ptr, sql_stmt0, -1, &stmt0, 0);
sqlite3_step(stmt0);
char sql_stmt1[128];
strlcpy(sql_stmt1, "UPDATE tbl_stock SET DESCRIPTION = ", sizeof(sql_stmt1));
strlcat(sql_stmt1, "'", sizeof(sql_stmt1));
strlcat(sql_stmt1, desc, sizeof(sql_stmt1));
strlcat(sql_stmt1, "'", sizeof(sql_stmt1));
strlcat(sql_stmt1, "WHERE BCID = '900012345';", sizeof(sql_stmt1));
ret = sqlite3_prepare_v2(db_ptr, sql_stmt1, -1, &stmt1, 0);
sqlite3_step(stmt1);
char sql_stmt2[128];
strlcpy(sql_stmt2, "COMMIT", sizeof(sql_stmt2));
strlcat(sql_stmt2, ";", sizeof(sql_stmt2));
ret = sqlite3_prepare_v2(db_ptr, sql_stmt2, -1, &stmt2, 0);
sqlite3_step(stmt2);
if (ret != SQLITE_OK) {
printf("Unable to update stock\n.");
sqlite3_close(db_ptr);
return 1;
}
sqlite3_finalize(stmt0);
sqlite3_finalize(stmt1);
sqlite3_finalize(stmt2);
sqlite3_close(db_ptr);
return 0;
}
一般來說,這與您可以從符合ACID的數據庫中獲得的一樣多。 有關詳細信息,請務必閱讀 SQLite 文檔,特別是 SQLite 中的原子提交和如何損壞 SQLite 數據庫文件
正如我進一步思考的那樣,我通過調用這個 sysctl 旋鈕sysctl debug.kdb.panic=1
在 FreeBSD 中產生 kernel 恐慌,對操作系統崩潰進行了簡單的模擬(這是我使用的操作系統)。 我在代碼的某些區域一次一個地應用這個旋鈕來生成 5 個場景。 在第 1、第 2、第 3 和第 4 種場景中,UPDATE 查詢沒有反映在數據庫中,只有在第 5 種場景中,使用 sqlite3_close(db_ptr) 關閉數據庫后發生恐慌,並且在所有這些場景中數據庫都沒有損壞。 這是修改后的代碼。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
int
main(void)
{
sqlite3 *db_ptr;
sqlite3_stmt *stmt0, *stmt1, *stmt2;
char desc[25];
int ret = 0;
ret = sqlite3_open("stock.db", &db_ptr);
if (ret != SQLITE_OK) {
printf("Database opening error\n");
}
printf("Modify description: ");
gets_s(desc, 24);
char sql_stmt0[128];
strlcpy(sql_stmt0, "BEGIN TRANSACTION", sizeof(sql_stmt0));
strlcat(sql_stmt0, ";", sizeof(sql_stmt0));
ret = sqlite3_prepare_v2(db_ptr, sql_stmt0, -1, &stmt0, 0);
sqlite3_step(stmt0);
system("sysctl debug.kdb.panic=1"); /* 1st scenario */
char sql_stmt1[128];
strlcpy(sql_stmt1, "UPDATE tbl_stock SET DESCRIPTION = ", sizeof(sql_stmt1));
strlcat(sql_stmt1, "'", sizeof(sql_stmt1));
strlcat(sql_stmt1, desc, sizeof(sql_stmt1));
strlcat(sql_stmt1, "'", sizeof(sql_stmt1));
strlcat(sql_stmt1, "WHERE BCID = '900012345';", sizeof(sql_stmt1));
ret = sqlite3_prepare_v2(db_ptr, sql_stmt1, -1, &stmt1, 0);
sqlite3_step(stmt1);
system("sysctl debug.kdb.panic=1"); /* 2nd scenario */
char sql_stmt2[128];
strlcpy(sql_stmt2, "COMMIT", sizeof(sql_stmt2));
strlcat(sql_stmt2, ";", sizeof(sql_stmt2));
ret = sqlite3_prepare_v2(db_ptr, sql_stmt2, -1, &stmt2, 0);
sqlite3_step(stmt2);
system("sysctl debug.kdb.panic=1"); /* 3rd scenario */
if (ret != SQLITE_OK) {
printf("Unable to update stock\n.");
sqlite3_close(db_ptr);
return 1;
}
sqlite3_finalize(stmt0);
sqlite3_finalize(stmt1);
sqlite3_finalize(stmt2);
system("sysctl debug.kdb.panic=1"); /* 4th scenario */
sqlite3_close(db_ptr);
system("sysctl debug.kdb.panic=1"); /* 5th scenario */
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.