簡體   English   中英

SQLite 電源故障或系統崩潰事務

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM