delphi使用unidac批量insert into插入sqlite数据库记录出现database is locked错误!

博客讲述在Delphi中用for循环向SQLite插入数据,插入48条以上出现“database is locked”错误。原因是SQLite只支持库级锁,同一时刻仅允许一个写操作。解决办法是避免重复打开数据库,引入单例方法与SQLiteOpenHelper类,还可设置BusyTimeout属性,经测试问题解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

就是写了一个for循环插入数据:
for j := 0 to Num - 1 do  
      begin
         ..........
         UniQuery1.SQL.Add('insert into .......
         UniQuery1.ExecSQL;
         .........
      end;  
错误现象:循环插入10条以内的数据,都不会出错,循环插入48条以上数据就出现:database is locked错误!

优快云百度了一下:C# 的,还是一头雾水,根据3楼的提示,或许是我对这个表在其他窗体已经Active Open了,导致出错?
SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite允许多个进程/线程同时进行读操作,但在同一时刻只允许一个线程进行写操作。SQLite在进行写操作时,数据库文件会被锁定,此时任何其他的读/写操作都会被阻塞,如果阻塞超过5秒钟(默认是5秒,可通过重新编译SQLite进行修改),就会抛出描述为“database is locked”的异常。

出现上述现象的原因是SQLite只支持库级锁,不支持并发执行写操作,即使是不同的表,同一时刻也只能进行一个写操作。例如,事务T1在表A新插入一条数据,事务T2在表B中更新一条已存在的数据,这两个操作是不能同时进行的,只能顺序进行。

SQLite尽量延迟了申请X锁,直到数据块真正写盘时才申请X锁,再加上被阻塞的操作有等待时间,所以当SQLite作为客户端嵌入数据库被使用时时,一般情况下不会抛出“database is locked”的异常。但是,在高并发的环境下,还是很有可能抛出异常的。避免这种异常的最简单有效的方法,就是在进行写操作时实现互斥锁,并保证写操作按顺序执行。

这边先说一下database is locked产生的原因:sqlite同一时间只能进行一个写操作,当同时有两个写操作的时候,后执行的只能先等待,如果等待时间超过5秒,就会产生这种错误.同样一个文件正在写入,重复打开数据库操作更容易导致这种问题的发生。

那首先,得避免重复打开数据库,首先引入单例方法与SQLiteOpenHelper类:

--------------------------------------------------------------------------------------------------------------------------

详细看了一下uniDAC文档,找到一个属性:BusyTimeout 可以调用:sqlite3_busy_timeout
代码如下:
 UniConnection1.SpecificOptions.Values['BusyTimeout'] := '10000';
结论:经测试问题解决;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值