[SQLite]關閉SQLite3中的journal暫存檔

摘要:關閉SQLite3中的journal暫存檔

相信很多使用SQLite3作為資料庫的人都會發現一個現象,那就是當SQLite3有做寫入的動作時,SQLite3會自動產生一個名為"資料庫名稱-journal"的暫存檔。這是做什麼用的呢?


答案是用來Rollback ,換句話說,就是當資料寫入資料庫有失敗動作時,透過journal檔案予以復原到未更動前(原始)資料,來確保資料完整與一致性。如果在每次寫入的時間很長或頻繁的進行資料庫寫入情況下,因系統(主機)電力不穩或突然斷電時,那麼下次重新啟動,而journal檔案若存在,則在開啟SQLite資料庫時,若發現有journal檔案的存在,便會對資料庫做Rollback 動作(還原)(詳細內容:http://www.sqlite.org/atomiccommit.html)。但是有時候系統(主機)電力不穩或突然斷電會導致journal檔案損毀,因而造成SQLite資料庫無法開啟[問題1]。必須(手動)刪除journal檔案,SQLite資料庫才能再度開啟。

 

 

目前所知的方法有兩種:

第一種方法:
在系統開機後第一次開啟或每一次使用SQLite資料庫時,先檢查是否已經存在journal檔案了,如果是則透過程式自動去刪除該journal檔案
但是這有個問題,因為自動刪除該journal檔案,導致沒有Rollback (還原)作用,無法保障資料完整與一致性。缺點二:有時候會發生程式無法自動刪除(如:
journal檔案嚴重損毀),而導致上面的問題(無法開啟資料庫)[問題1]再度發生。

 

第二種方法:
使用"PRAGMA journal_mode = OFF"指令,這個指令能關閉自動產生journal暫存檔動作。
但是如此一來當在寫入資料庫的過程,一旦發生意外狀況,將會導致SQLite資料庫無法保障資料完整與一致性。缺點二:journal_mode設定為OFF時,無法使用交易模式(Transaction)進行操作。

 

第二種方法的缺點二在如果需要使用交易模式(Transaction)進行操作時,可以透過"PRAGMA journal_mode = DELETE"指令,修改回原本的journal模式(journal_mode),就可以使用交易模式(Transaction)

 

下面的程式碼便是第二種方法的實作

//請先引用 using System.Data.SQLite;

const string path = @"C:\testDB.db3";//SQLite資料庫檔案路徑

if (File.Exists(path))//判斷檔案是否存在。是
{
    File.Delete(path);
}

SQLiteConnection.CreateFile(path);//建立SQLite資料庫檔案

using (SQLiteConnection conn = new SQLiteConnection("Data Source=" + path + ";Version=3;"))//建立連線
{
                    
    using (SQLiteCommand comm = conn.CreateCommand())
    {
        conn.Open();//開啟資料庫

        comm.CommandText = "PRAGMA journal_mode=OFF;";//journal mode 設定為 OFF(關閉journal模式)
        comm.ExecuteNonQuery();
        //---下面便只會以journal_mode=Off方式,進行操作-----
                        
        //---做一些操作-------------------------------------
        comm.CommandText = "CREATE TABLE text_table(id int, value text);";//建立'text_table'資料表
        comm.ExecuteNonQuery();

        for (int i = 0; i < 10; ++i)
        {
            //新增一筆(列)資料到資料表
            comm.CommandText = "Insert INTO text_table (id, value) VALUES (0, 'Hello World')";
            comm.ExecuteNonQuery();
        }
        //---------------------------------------------------
    }
}

 

若如果在確定操作SQLite資料庫時,完全不需要使用交易模式(Transaction)下,則下面的程式碼,可以在與資料庫連線時便先設定以journal mode = OFF模式,進行連線。不需要像上面的程式碼額外執行 "PRAGMA journal_mode=OFF;"此一段指令。更方便!!

//請先引用 using System.Data.SQLite;

const string path = @"C:\testDB.db3";//SQLite資料庫檔案路徑

if (File.Exists(path))//判斷檔案是否存在。是
{
    File.Delete(path);
}

SQLiteConnection.CreateFile(path);//建立SQLite資料庫檔案

using (SQLiteConnection conn = new SQLiteConnection("Data Source=" + path + ";Version=3;journal_mode=OFF;"))//建立以關閉journal模式(journal mode=OFF)下進行連線
{
                    
    using (SQLiteCommand comm = conn.CreateCommand())
    {
        conn.Open();//開啟資料庫

        //---下面便只會以journal_mode=Off方式,進行操作-----
                        
        //---做一些操作-------------------------------------
        comm.CommandText = "CREATE TABLE text_table(id int, value text);";//建立'text_table'資料表
        comm.ExecuteNonQuery();

        for (int i = 0; i < 10; ++i)
        {
            //新增一筆(列)資料到資料表
            comm.CommandText = "Insert INTO text_table (id, value) VALUES (0, 'Hello World')";
            comm.ExecuteNonQuery();
        }
        //---------------------------------------------------
    }
}

 

感恩下面的作者

相關參考:http://www.wretch.cc/blog/zevoid/647203