开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 273|回复: 2
收起左侧

[已解决] Sqlite数据库多开调用问题

 关闭 [复制链接]
结帖率:92% (222/241)
发表于 2024-1-24 20:48:22 | 显示全部楼层 |阅读模式   广东省梅州市
11精币
请问下 Sqlite数据库 如果开几十个软件 同时大量连接调用 cha询,会不会出现有的软件正在连接数据库cha询,其他软件就不能进行连接数据库的情况呢

最佳答案

查看完整内容

数据库是可以并发的

回答提醒:如果本帖被关闭无法回复,您有更好的答案帮助楼主解决,请发表至 源码区 可获得加分喔。
友情提醒:本版被采纳的主题可在 申请荣誉值 页面申请荣誉值,获得 1点 荣誉值,荣誉值可兑换荣誉会员、终身vip用户组。
快捷通道:申请荣誉值无答案申请取消悬赏投诉有答案未采纳为最佳
发表于 2024-1-24 20:48:23 | 显示全部楼层   辽宁省锦州市
数据库是可以并发的

评分

参与人数 1荣誉 +1 收起 理由
笨潴 + 1 热心帮助他人,荣誉+1,希望继续努力(*^__^*) 嘻嘻!

查看全部评分

回复

使用道具 举报

发表于 2024-1-24 20:51:52 | 显示全部楼层   辽宁省锦州市
SQLite是知名的嵌入式数据库,一个dll只有1MB。开源,纯C,单文件且提供许多功能开关,编译非常方便。

一般认为SQLite的并发性不高,其实按官网的说法,它已经是嵌入式数据库中并发性最高的了。

本文为阅读官方文档加上自己实验后的总结。

读写锁
SQLite锁的级别依次是:NoLock Shared Reserved Pending Exclusive。

Shared是一般意义上的读锁,允许同时有多个并发读
Exclusive是一般意义上的写锁,只允许有一个,作用于整个数据库文件,不允许其它连接读,只有自己能读写
Reserved是写日志阶段时的锁,也只允许有一个。关键是此时仍能加读锁,只是不能再加Reserved或更高级别的锁
Pending是Commit时发生的,会阻止加新的读锁,等所有已有读锁都释放了就进入Exclusive
对于一个事务,刚开始Select的时候只有Shared锁,等开始DML了就会加Reserved锁,Commit时进入Pending阶段,如果一段时间内没等到所有的读锁都释放,锁就升级失败。

隔离级别
隔离级别默认情况下是最高的Serializable。

脏读:

事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的。
T1修改了没提交,T2读不到T1的内容,因为T1只往日志里写了东西,T2是直接读的文件。因此不会出现脏读。

不可重复读:

事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
T1和T2都能读取,此时T1存在读锁,T2可以修改但无法提交,此情形同脏读。因此不会出现不可重复读。

幻读:

第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行。
T1修改了没提交,存在写锁,T2无法修改;或者T1一开始读取了,存在读锁,T2能修改但无法提交。总之此时无法修改数据库,因此不会出现幻读。

WAL下的隔离级别
启用WAL模式后,SQLite的隔离性变为Snapshot。

锁的行为变为即使是Exclusive也允许读取,某一事务也能写入,即读写之间可以并发,这大大增加了性能。只不过可能读到的是旧数据,即读不到确实已提交的内容,只有本连接所有读锁都释放或者新连接才能读到已提交的内容;上一段都是直接无法提交的。当然,多个写之间仍无法并发。

脏读:无变化
不可重复读:T2可以提交,且T1读到的仍是提交前的内容
幻读:T1修改了没提交,T2无法修改;或者T1读取了,T2可以修改也能提交,此情形同上一点
因此三种问题还是都不会出现。

不过引入了一个新问题。假如T1读取了,T2修改并提交,T1再想提交时,数据库已经不是最新的了,它修改的是老版本的快照。此时该语句会简单的失败,不会去分析两者修改的范围是否有冲突,或者说冲突的检测范围是整个数据库文件。
解决办法是对于T1使用BEGIN IMMEDIATE语句,这样T1在一开始就获得了写锁,T2无法修改。

多线程
SQLite有三种线程模式:单线程、多线程、Serialized。注意此处的Serialized与隔离级别中的Serializable没有关系。

官网的说法:

当编译期参数SQLITE_THREADSAFE设为1时(也是一般情况下的默认值),“SQLite can be safely used by multiple threads with no restriction”
当它设为2时,“SQLite can be safely used by multiple threads provided that no single database connection is used simultaneously in two or more threads”
当它设为0时,“SQLite is unsafe to use in more than a single thread at once”
按照此说法,默认情况下多线程怎么使用都没问题;设为2时,对于某一连接,只要同一时间只有一个线程使用就没问题;设为0时,一次只能有一个线程。

但是许多网友的建议比较保守,大家认为即使设为1,也不能重用连接。即一个线程可以创建多个连接,但在本线程创建的连接不能传递给其它线程使用,同一连接也不能同时有多个活动的游标。Python的sqlite3模块和System.Data.SQLite3(这是SQLite官方维护的)都是这种行为。这当然是最安全的,但却比官网说法设为2时还严格,官网设为2时也没说不能重用,只是说不能同时使用。另外官方CLI设为了0。

我对官网这些话的理解:设为1时一个连接可以有多个游标,也可以重用。设为2时仍然可以有多个游标也能重用,但是不要多个线程使用同一个连接,各个线程要用的时候自己新建连接即可。设为0时仍然支持多进程连接,但对于单一的进程,一次就只能使用一个连接。
cache=shared
在此模式下,多个连接会“像”单个连接。

只有此模式下再加上PRAGMA read_uncommitted = on;才会在此连接切换到读未提交的隔离级别,此时即使有Exclusive锁也能读取,我觉得意义不大。

正常情况下,开启此模式,隔离性仍然是Serializable;这些连接内部又会有一些锁用于保证序列化。

按我理解,当需要单进程创建多个连接时,无脑开,就能节约资源。

总结
我觉得SQLite蛮好的。

普通的优点有:体积极小、不用研究创建用户、一个文件就是一个数据库、默认最高隔离级别保证数据准确。

并发性上,我觉得即使每次使用都创建新的连接也没有问题,更不论上面讨论了那么多的优化手段了,毕竟是单机项目。

虽然没有储存过程,但现在开发的理念一般认为数据库只拿来存东西,逻辑应放在普通编程语言的代码里。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 诚聘英才| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 800073686,邮箱:800073686@b.qq.com
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表