导航:
论坛 -> 数据库专区
斑竹:liumazi,waterstone
作者:
glwang (glwang)
★☆☆☆☆
-
盒子活跃会员
2019/4/11 9:00:01
标题:
求助:delphi使用unidac批量insert into插入sqlite数据库记录出现database is locked错误!
浏览:2074
加入我的收藏
楼主:
就是写了一个for循环插入数据: for j := 0 to Num - 1 do begin .......... UniQuery1.SQL.Add('insert into ....... UniQuery1.ExecSQL; ......... end; 错误现象:循环插入10条以内的数据,都不会出错,循环插入48条以上数据就出现:database is locked错误!
----------------------------------------------
作者:
2019/4/11 9:03:34
1楼:
先拼接,再一次执行~ 不要一条一执行~ 类似这样: for j := 0 to Num - 1 do begin .......... UniQuery1.SQL.Add('insert into ....... ......... end; UniQuery1.ExecSQL;
----------------------------------------------
-
作者:
glwang (glwang)
★☆☆☆☆
-
盒子活跃会员
2019/4/11 14:36:02
2楼:
1楼的方案试了,还是报错:database is locked!百度了一下:好像是sqlite数据库的先天设计缺陷,如何解决?
----------------------------------------------
作者:
2019/4/11 15:11:33
3楼:
好奇怪,楼主的 for 难道和我们的不同吗? 我们的 for 是单线程的。代码是顺序执行的。不可能产生 锁定。
----------------------------------------------
(C)(P)Flying Wang
作者:
glwang (glwang)
★☆☆☆☆
-
盒子活跃会员
2019/4/11 15:18:24
4楼:
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”的异常。但是,在高并发的环境下,还是很有可能抛出异常的。避免这种异常的最简单有效的方法,就是在进行写操作时实现互斥锁,并保证写操作按顺序执行。 ---------- 作者:time式 来源:CSDN 原文:https://blog.csdn.net/WZh0316/article/details/81188451 版权声明:本文为博主原创文章,转载请附上博文链接!
----------------------------------------------
作者:
glwang (glwang)
★☆☆☆☆
-
盒子活跃会员
2019/4/11 15:20:11
5楼:
这边先说一下database is locked产生的原因:sqlite同一时间只能进行一个写操作,当同时有两个写操作的时候,后执行的只能先等待,如果等待时间超过5秒,就会产生这种错误.同样一个文件正在写入,重复打开数据库操作更容易导致这种问题的发生。 那首先,得避免重复打开数据库,首先引入单例方法与SQLiteOpenHelper类: ---------- 作者:LoveWyf_ 来源:CSDN 原文:https://blog.csdn.net/qq_25412055/article/details/52414420 版权声明:本文为博主原创文章,转载请附上博文链接!
----------------------------------------------
作者:
2019/4/11 15:54:56
6楼:
问题在于,我们的 for 不可能同时的。所以肯定是 一个写操作。不可能超过1。
----------------------------------------------
(C)(P)Flying Wang
作者:
glwang (glwang)
★☆☆☆☆
-
盒子活跃会员
2019/4/11 16:18:52
7楼:
比如我 for 了6次以内基本没有问题,都能插入记录,num数值如果是超过10例如:48,就只能成功插入几条记录然后就报错:database is locked 我后来在for循环里面加了一个:sleep(100);稍微好点,能支持插入10多条,但是还是达不到项目要求的48条连续插入记录的要求。 for j := 0 to Num - 1 do begin .......... UniQuery1.SQL.Add('insert into ....... UniQuery1.ExecSQL; sleep(100); ......... end;
----------------------------------------------
作者:
2019/4/11 16:41:18
8楼:
我写的 sqlite 数据库每天都要用事务更新近 20万条数据,没这事啊 for j := 0 to Num - 1 do begin .......... UniQuery1.SQL.Add('insert into ....... UniQuery1.ExecSQL;<-------别再在这里搞 sleep(100); ......... end; //用事务 ...StartTransaction; ...Add('insert into tab (col) VALUES (:col); for .... .Params[0].AsString := ... Query.ExecSQL; end; ....Conn.Commit; ...EndTransaction;<---不知道 uniDAC 有没有这个
----------------------------------------------
delphi 是兴趣,和工作无关,即使它倒闭。又不靠它 delphi 吃饭,怕甚?
作者:
glwang (glwang)
★☆☆☆☆
-
盒子活跃会员
2019/4/11 17:12:44
9楼:
感谢8楼方案,我的代码乱,懒得改了,我又百度了一下:sqlite3给的函数sqlite3_busy_timeout来实现了延时(时间的延时) //sqlite3_busy_timeout实际上是封装了sqlite3_busy_handler,这里面sqlite3_busy_handler调用的是个固定的回调,通过这个回调实现了固定时间的延时. sqlite3_busy_timeout(db, 30*1000); //最长等待30m ,也相当于延时 sqlite3_exec(db , sqlcmd , NULL, NULL, &zErrMsg ); sqlite3_close(db); ---------- 详细看了一下uniDAC文档,找到一个属性:BusyTimeout 可以调用:sqlite3_busy_timeout 代码如下: UniConnection1.SpecificOptions.Values['BusyTimeout'] := '10000'; 结论:经测试问题解决;
----------------------------------------------
作者:
2019/4/11 18:27:23
10楼:
SQLITE是单连接数据库,当已经有一个连接,试图再连,就会报:database is locked 这个不是先天缺陷,也不是BUG,这是它的设计初衷——只支持一个数据库连接,你可以理解为它是独占的。
----------------------------------------------
中间件QQ群: 92449782 博客: http://www.cnblogs.com/hnxxcxg/
作者:
2019/4/11 19:08:03
11楼:
用 FireDAC 1 秒插入SQLite 几万条很轻松。
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
2019/4/11 19:40:08
12楼:
从没用过这么少的字段,随手写了demo测试下,发现速度快到让人窒息。
此帖子包含附件: 大小: 40.2K
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
glwang (glwang)
★☆☆☆☆
-
盒子活跃会员
2019/4/12 9:07:38
13楼:
10楼:“SQLITE是单连接数据库,当已经有一个连接,试图再连,就会报:database is locked” 我估计我的程序就是这个原因,由于数据库表业务关联很乱,窗体多,一时理不清。。。,使用sqlite3_busy_timeout虽然可以解决报错问题,但会导致插入大量记录的时候耗时太多
----------------------------------------------