摘要:關閉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();
}
//---------------------------------------------------
}
}
感恩下面的作者