解决SQLite中的 database is locked

前些时候,同事在站点服务端使用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的文件锁来实现库级锁,粒度很大,但是,它通过一些复杂特殊的处理(具体可以参见分析系列),尽量的提升了读写的并发度。
  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”错误。

我们可以编写一个测试案例,代码很简单的,并发的执行多条update语句,使用不同的机子,一般选择一个性能好点的机子(我测试的时候使用的是G4)和一个性能差点的机子(G2)

测试发现,在G2机器上,跑了不到半分钟,大概执行了500条Update语句,Sqlite就报错,提示“ database is locked”,但是在G4机器上很难发现,这也就解释了开发机上难重现而在客户服务器上报错的现象。

这里要仔细看一下上面标注红色的内容,因为我刚开始没有使用任何同步机制来进行操作的,使用的G4手机测试的,结果一运行就报错,所以上网查询原因,结果说是对一个表进行操作的时候,需要进行加锁,所以我就在对同一个表进行CRUD操作的时候,使用了同一个锁,运行没有错,但是过了几天之后,测试那边的人给一个bug表,尽然出现了上面的问题,而且是G2机器,所以我就用这个机器进行测试,果然发现会出现上述的问题,这时候就很纠结了,网上各种搜索,无果,结果看到一篇文章说到了重点,说sqlite是库级锁,那么我就将上面的表级锁改成了库级锁(很简单,不同的表都是用同一个锁),在测试发现没有上述问题了。。

解决SQLite中的 database is locked

时间: 2024-08-02 22:03:31

解决SQLite中的 database is locked的相关文章

SQLITE报错database is locked的解决办法

用firedac连接SQLITE数据库,空间tdbedit绑定字段name,如下语句修改其值时报错. procedure TForm1.Button3Click(Sender: TObject);begin fdquery.Edit; fdquery.FieldByName('name').AsString:='test2'; fdquery.post;   //执行到这里报错 [FireDAC][Phys][SQLite] ERROR: database is locked. 换成refres

sqlite:多线程操作数据库“database is locked”解决方法(二)

上一篇博客<sqlite:多线程操作数据库“database is locked”解决方法>通过注册延时函数的方法来处理数据库被锁的问题.此方法固然能解决问题,但是在多个线程向数据库写入大量数据的情况下,延时会拖慢进度. 想出方法二: 1. 创建一个链表,链接如下格式的结构体,线程1,线程2,线程3......不直接改写数据库,而是把sql语句插入链表中: typedef struct { uint8_t *buf; uint32_t len; } sqlItem_t; 2. 创建一个独立的线

解决SQLite database is locked

前些时候,同事在站点服务端使用SQlite存储一些临时数据,但是在多人并发的时候Sqlite会抛出异常:The database file is locked , database is locked,而且这个是在客户生产环境下提示出来的,开发环境很难重现,同事实在没辙,竟然想发动所有研发同事通过操作软件重现问题,我只能呵呵了.既然是Sqlite的原因,直接写个小程序测试下sqlite不就行了,而且就算重现了,难不成要改Sqlite源码... Sqlite的特点: 简单(simple):SQLi

dpkg: error: dpkg status database is locked by another process 解决方法

https://i.cnblogs.com/EditPosts.aspx?opt=1使用dpkg -i/apt命令安装,报错: ------------------------------------------------------------- dpkg: error: dpkg status database is locked by another process 无法获得锁 /var/lib/apt/lists/lock - open ------------------------

转发 FMDB多线程下&quot;is currently in use&quot; 或者 &quot;database is locked&quot; 问题

FMDB多线程下"is currently in use" 或者 "database is locked" 问题 问题一: "is currently in use" 出现的场景是这样的,多线程操作数据库,每个线程都使用了FMDatabase实例(注意没有使用FMDatabaseQueue). 问题二:“database is locked"出现的场景是这样的,多线程操作数据库,每个线程各自创建了FMDatabaseQueue实例操作数

FMDB多线程下&quot;is currently in use&quot; 或者 &quot;database is locked&quot; 问题

问题一: "is currently in use" 出现的场景是这样的,多线程操作数据库,每个线程都使用了FMDatabase实例(注意没有使用FMDatabaseQueue). 问题二:“database is locked"出现的场景是这样的,多线程操作数据库,每个线程各自创建了FMDatabaseQueue实例操作数据库,或者一个线程创建FMDatabaseQueue实例来操作,而另外的线程创建了FMDatabase实例来操作. 解决:FMDB多线程操作数据库,必须使

使用FMDB多线程访问数据库,及database is locked的问题

今天终于解决了多线程同时访问数据库时,报数据库锁定的问题,错误信息是: Unknown error finalizing or resetting statement (5: database is locked) 最后通过FMDatabaseQueue解决了这个问题,本文总结一下: FMDatabase不能多线程使用同一个实例 多线程访问数据库,不能使用同一个FMDatabase的实例,否则会发生异常.如果线程使用单独的FMDatabase实例是允许的,但是同样有可能发生database is

解决SQLite异常:library routine called out of sequence

在项目开发中,使用SQLite一不小心就会碰到各种DB异常,网上搜了下没有这方面的资料,写出来记录下. 异常信息:android.database.sqlite.SQLiteMisuseException: library routine called out of sequence: , while compiling: ...... 解决这种异常有2个办法:方法一:单例模式使用DB时,函数[方法]上加同步synchronized即可解决. 方法二:工厂模式使用DB也可以解决(或者在线程中ne

java.lang.UnsupportedOperationException: Database is locked

今天在部署jira系统的时候报错: java.lang.UnsupportedOperationException: Database is locked 原因分析:造成这个错误的原因有很多,如果你是在安装一个新的数据库,那么有可能是entityengine.xml配置错误引起的,也有可能是你的数据库需要修复,也就是说你的数据库出了问题. 解决方法: 必须要删除这个三个:remove three things-- .jira-home.lock .bundled-plugins/ and .os