事务和数据库锁

    事务定义了一组SQL命令的边界,这组命令或者作为一个整体被全部执行,或者都不执行,这称为数据库完整性的原子性原则.

事务的范围

事务由3个命令控制:begin,commit和rollback.begin开始一个事务,begin之后的所有操作都可以取消,如果连接终止前没有发出commit,也会被取消.commit提交事务开始所后执行的所有操作,rollback还原begin之后所有的操作.

sqlite> begin;

sqlite> delete from test;

sqlite> rollback;

sqlite> select count(*) from test;

比如上面开始了一个事务,先删除了test表中所有的行,但是有用rollback进行了回滚.在执行select时.你会发现表中没有发生任何改变.

默认情况下,SQLite中每条SQL语句自成事务(自动提交模式).也就是说,如果没有手动使用begin...commit/rollback定义事务的范围,SQLite默认每条单独的SQL命令就是begin....commit/rollback的事务.这种情况下,所有成功完成的命令都自动提交.同样.所有遇见错误的命令都回滚,

冲突的解决

违反约束会导致事务的终止.SQLite有其独特的方法指定不同的方式来处理约束违反,这种功能称为冲突解决.SQLite提供五种可能的冲突解决方案:

replace:当违反了唯一性约束时,SQLite将造成这种违反的记录删除,以插入货修改的新纪录代替,SQL继续执行,且不报错.

ignore:当违反约束时,SQLite允许命令继续执行,违反约束的行保持不变.,它之前之后的记录继续修改,且不报错.

fail:当违反约束时,SQLite终止命令,但是不恢复约束违反之前已经修改的记录.在约束违法发生前的改变将保留.

abort(SQLite默认的冲突解决方法):当违反约束时,SQLite恢复命令所做的所有改变并终止命令.abort是最昂贵的冲突解决方案,要求额外的工作.

rollback:当违反约束时,SQLite执行回滚.终止当前命令和整个事务.

冲突解决方法可以在SQL明命令中指定,也可以在表和索引的定义中执行,冲突解决策略紧跟在insert或者update后面,.并加上前缀or,例如:

update or fail test set id=100 modified='yes';

insert or ignore into from test values('aaron');

也可以在表内定义时,为单个字段指定冲突解决方法,例如:

create temp table cast(name text unique on conflict rollback);

数据库锁

在Sqlite中,锁和事务是紧密联系的.SQLite采用粗粒度的锁.当一个连接要写数据库时,所有其他的连接被锁住,知道写连接结束它的事务.SQLite使用锁逐步提升机制,为了写数据库,连接需要逐级获得排他锁.SQLite有5种不同的锁状态:未加锁(unlocked),共享(shared),预留(reserved),未决(pending)和排他(exclusive).每个数据库连接在同一时刻只能处于其中一个状态,每种状态(未加锁状态除外)都有一种锁与之对应.SQlite锁转换图如下图所示:


最初的状态是未加锁状态,在此状态下,连接还没有访问数据库.当连接一个数据库,甚至已经用begin开始了一个事务时,连接都还处于未加锁状态.

未加锁状态的下一个状态就是共享状态.为了能够从数据库中读(而不是写)数据,连接必须首先进入共享状态,也就是说,首先要获得一个共享锁.多个连接可以同时获得并保持共享锁,也就是说,多个连接可以同时从一个数据库中读取数据,但是哪怕只有一个共享锁还没有释放,也不允许任何连接写数据库.

如果一个连接想要写数据库,他必须首先获得一个预留锁.一个数据库同时只能有一个预留锁,该预留锁可以与共享锁共存,他是写数据库的第一阶段,预留锁既不阻止其他拥有共享锁的连接继续读数据可,也不阻止其他连接获得新的共享锁.

一旦一个连接获得了预留锁,他就可以开始处理数据库修改的操作了,尽管这些修改只能在缓冲区中进行,而不是实际写到磁盘,对读出内容所做的修改保存在内存缓冲区.当连接想要提交修改(或事务)时,为了得到排他锁,必须首先将预留锁提升为未决锁.获得未决锁之后,其他连接就不能在获得新的共享锁了,但已经拥有共享所的连接仍然可以继续正常读取数据库,此时,拥有未决锁的连接等待其他拥有共享锁的连接完成工作并释放共享锁.

一旦所有的其他的共享锁都被释放,拥有未决锁的连接就可以将其锁提升为排他锁,此时就可以自由的对数据库进行修改,所有以前所缓存的修改都会被写到数据库文件中.

事务类型

SQLite有三种不同的事务类型,他们以不同的锁状态启动事务.事务可以开始于:deferred,immediate和exclusive.事务类型在begin命令中指定:

begin [deferred | immediate | exclusive ] transaction

一个deferred直到必须使用时才获取锁.因此,对于延迟事务,begin语句本身不会做什么事情,它从未锁定状态开始.这是默然的情况.

由begin开始的immediate事务在begin执行时试图获取预留锁.若果成功,begin immediate 保证没有其他的连接可以写数据库,其他的连接可以继续对数据可进行读操作.预留锁的其他结果是没有其他连接能成功启动begin immedicate 或者begin exclusive 命令,当其他连接执行上述命令时,SQLite会返回SQLITE_BUSY错误.这时您可以对数据库进行修改操作,但是调用commit时,如果其他的读事务还没有完成,会返回SQLITE_BUSY错误,需要等他们执行完毕才能提交事务.

exclusive事务会试着获取对数据库的排他锁,一旦成功,exclusive事务保证数据库中没有其他的活动连接,所以可对数据库进行任意的读写操作.

基本的准则是:如果使用的数据库没有其他连接,用begin就足够了,但是,如果使用的数据库有其他也会对数据库进行写操作的连接,就得使用begin immedicate 或者begin exclusive 开始事务.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容