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

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

CSDN百度了一下: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';
结论:经测试问题解决;

猜你喜欢

转载自blog.csdn.net/xyzhan/article/details/89787879