前些时候,同事在站点服务端使用sqlite存储一些临时数据,但是在多人并发的时候sqlite会抛出异常:The database file is locked,database is locked,而且这个是在客户生产环境下提示出来的,开发环境很难重现,同事实在没辙,竟然想发动所有研发同事通过 *** 作软件重现问题,我只能呵呵了。既 然是sqlite的原因,直接写个小程序测试下sqlite不就行了,而且就算重现了,难不成要改sqlite源码...
sqlite的特点:
简单(simple):sqlite是一个非常轻量级自包含(lightweight and self-contained)的DBMS:一个头文件,一个动态库文件,你就拥有了关系数据库的所有功能了。简单,是sqlite最明显的哲学。它提供 的API少而简单。只需要一个DLL文件,你的程序马上就拥有了一个功能强大的数据库引擎,这是一件很美妙的事。
小巧(small):我用VS 2005在windows下编译的3.6.11,Release版为368K,用时不到20秒——而编译MysqL时,要花上几分钟。而当我插入10000条int数据时,内存开销660K,磁盘开销92K。
事务(transaction):事务是现代商业数据处理系统最基本的要求,而Access,不论是在可执行文件大小(看了一下Access2003的可执行文件大小为6.32M,两者不是一个量级),还是事务特性,都是不能和sqlite 相比的。
并发性(Concurrency):由于sqlite通过OS的文件锁来实现库级锁,粒度很大,但是,它通过一些复杂特殊的处理(具体可以参见分析系列),尽量的提升了读写的并发度。如果你还有担心,你可以看看这篇文章:http://www.dbanotes.net/database/sqlite_cms.html。
sql92:sqlite支持绝大部分的标准SQL语句,你只需要几百K的空间,就可以换来需要上百兆的通用DBMS几乎所有 *** 作了。
方便(ConvenIEnce):如果你的程序要使用sqlite,只需要将拷贝你的程序目录即可。
开源(Opensource):这是它最强大的地方。开源,意味着你可以品读它的源码,你可以随时修改它,加入你自己的特性,而这一切完全免费的。开源,是一种精神
sqlite只支持库级锁,库级锁意味着什么?——意味着同时只能允许一个写 *** 作,也就是说,即事务T1在A表插入一条数据,事务T2在B表中 插入一条数据,这两个 *** 作不能同时进行,即使你的机器有100个cpu,也无法同时进行,而只能顺序进行。表级都不能并行,更别说元组级了——这就是库级 锁。但是,sqlite尽量延迟申请X锁,直到数据块真正写盘时才申请X锁,这是非常巧妙而有效的。
上面的介绍可以看出sqlite其实是一个客户端嵌入数据库,在高并发的服务器上是无法适用的,同事百度后,发现连接串中加入 "Journal Mode=WAL;"可以缓解并发压力,可是客户生产环境仍然出现“database is locked”错误。
测试程序如下:
staticvoIDMain(string[]args){for(inti=0;i<140;i++){ParameterizedThreadStartpStart=newParameterizedThreadStart(ClIEntTest.Excute);Threadtd=newThread(pStart);td.Start(1012+i);}Console.Read();}classClIEntTest{publicstaticvoIDExcute(ObjectID){boolflag=true;while(true){if(flag){stringsql="updateasr_infosetasr_check=1whereID='"+ID.ToString()+"'";sqlite.Executesql(sql);flag=false;}else{stringsql="updateasr_infosetasr_check=0whereID='"+ID.ToString()+"'";sqlite.Executesql(sql);flag=true;}}}}
测试发现,在i5 2.5Ghz 四核的机器上,跑了不到半分钟,大概执行了500条Update语句,sqlite就报错,提示“database is locked”,但是在差一点的机器上很难重现,这也就解释了开发机上难重现而在客户服务器上报错的现象。
解决办法:
privatestaticReadonlyobjectobj=newobject();privatestaticintExecuteNonquery(stringStrsql,CommandTypeCmdType,sqliteParameter[]sqliteParams){sqliteConnectionsqliteConn=newsqliteConnection(strConn);sqliteCommandsqliteCmd=sqliteCommandConstructor(sqliteConn,Strsql,CmdType,sqliteParams);if(sqliteConn.State!=ConnectionState.Open){sqliteConn.open();}Monitor.Enter(obj);intresult=sqliteCmd.ExecuteNonquery();Monitor.Exit(obj);//aaa++;//Console.Writeline(aaa);sqliteCmd.dispose();sqliteConn.Close();returnresult;}
事实证明sqlite不支持并发执行写入 *** 作,即使是不同的表,只支持库级锁,而且这个sqlite本身没有实现,必须自己实现这个库级锁。
总结以上是内存溢出为你收集整理的解决SQLite database is locked全部内容,希望文章能够帮你解决解决SQLite database is locked所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)