解決SQLite database is locked

來源:互聯網
上載者:User

標籤:blog   http   io   ar   os   使用   sp   for   檔案   

 

  前些時候,同事在網站服務端使用SQlite儲存一些臨時資料,但是在多人並發的時候Sqlite會拋出異常:The database file is locked , database is locked,而且這個是在客戶生產環境下提示出來的,開發環境很難重現,同事實在沒轍,竟然想發動所有研發同事通過操作軟體重現問題,我只能呵呵了。既然是Sqlite的原因,直接寫個小程式測試下sqlite不就行了,而且就算重現了,難不成要改Sqlite源碼...

  Sqlite的特點:

  1. 簡單(simple):SQLite是一個非常輕量級自包含(lightweight and self-contained)的DBMS:一個標頭檔,一個動態庫檔案,你就擁有了關聯式資料庫的所有功能了。簡單,是SQLite最明顯的哲學。它提供的API少而簡單。只需要一個DLL檔案,你的程式馬上就擁有了一個功能強大的資料庫引擎,這是一件很美妙的事。
  2. 小巧(small):我用VS 2005在Windows下編譯的3.6.11,Release版為368K,用時不到20秒——而編譯MySQL時,要花上幾分鐘。而當我插入10000條int資料時,記憶體開銷660K,磁碟開銷92K。
  3. 事務(transaction):事務是現代商業資料處理系統最基本的要求,而Access,不論是在可執行檔大小(看了一下Access2003的可執行檔大小為6.32M,兩者不是一個量級),還是事務特性,都是不能和SQLite 相比的。
  4. 並發性(Concurrency):由於SQLite通過OS的檔案鎖來實現庫級鎖,粒度很大,但是,它通過一些複雜特殊的處理(具體可以參見分析系列),盡量的提升了讀寫的並發度。如果你還有擔心,你可以看看這篇文章:http://www.dbanotes.net/database/sqlite_cms.html。
  5. SQL92:SQLite支援絕大部分的標準SQL語句,你只需要幾百K的空間,就可以換來需要上百兆的通用DBMS幾乎所有操作了。
  6. 方便(Convenience):如果你的程式要使用SQLite,只需要將拷貝你的程式目錄即可。
  7. 開源(Opensource):這是它最強大的地方。開源,意味著你可以品讀它的源碼,你可以隨時修改它,加入你自己的特性,而這一切完全免費的。開源,是一種精神

  SQLite只支援庫級鎖,庫級鎖意味著什嗎?——意味著同時只能允許一個寫操作,也就是說,即事務T1在A表插入一條資料,事務T2在B表中插入一條資料,這兩個操作不能同時進行,即使你的機器有100個CPU,也無法同時進行,而只能順序進行。表級都不能並行,更別說元組級了——這就是庫級鎖。但是,SQLite盡量延遲申請X鎖,直到資料區塊真正寫盤時才申請X鎖,這是非常巧妙而有效。

  上面的介紹可以看出Sqlite其實是一個用戶端嵌入資料庫,在高並發的伺服器上是無法適用的,同事百度後,發現串連串中加入 "Journal Mode=WAL;"可以緩解並發壓力,可是客戶生產環境仍然出現“database is locked”錯誤。

  測試程式如下:

        static void Main(string[] args)        {             for (int i = 0; i < 140; i++)             {                 ParameterizedThreadStart pStart = new      ParameterizedThreadStart(ClientTest.Excute);                 Thread td = new Thread(pStart);                 td.Start(1012 + i);             }             Console.Read();        }    class ClientTest    {        public static void Excute(Object id)        {            bool flag = true;            while (true)            {                if (flag)                {                    string sql = "update asr_info set asr_check = 1 where id = ‘" + id.ToString() + "‘";                    Sqlite.ExecuteSql(sql);                    flag = false;                }                else                {                    string sql = "update asr_info set asr_check = 0 where id = ‘" + id.ToString() + "‘";                    Sqlite.ExecuteSql(sql);                    flag = true;                }            }        }    }

  測試發現,在i5 2.5Ghz 四核的機器上,跑了不到半分鐘,大概執行了500條Update語句,Sqlite就報錯,提示“ database is locked”,但是在差一點的機器上很難重現,這也就解釋了開發機上難重現而在客戶服務器上報錯的現象。

  解決辦法:

        private static readonly object obj = new object();        private static int ExecuteNonQuery(string StrSQL, CommandType CmdType, SQLiteParameter[] SQLiteParams)        {            SQLiteConnection SQLiteConn = new SQLiteConnection(strConn);            SQLiteCommand SQLiteCmd = SQLiteCommandConstructor(SQLiteConn, StrSQL, CmdType, SQLiteParams);            if (SQLiteConn.State != ConnectionState.Open)            {                SQLiteConn.Open();            }            Monitor.Enter(obj);            int result = SQLiteCmd.ExecuteNonQuery();            Monitor.Exit(obj);            //aaa++;            // Console.WriteLine(aaa);            SQLiteCmd.Dispose();            SQLiteConn.Close();            return result;        }

  事實證明Sqlite不支援並發執行寫入操作,即使是不同的表,只支援庫級鎖,而且這個Sqlite本身沒有實現,必須自己實現這個庫級鎖。

解決SQLite database is locked

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.