sqlite的事务和锁

来源:互联网 发布:淘宝先行赔付 编辑:程序博客网 时间:2024/04/25 07:58
一、事务 :
事务定义了一组SQL命令的边界,这组命令或者作为一个整体被全部执行,或者都不执行。事务的典型实例是转帐。 
二、事务的范围 :
事务由3个命令控制:BEGIN、COMMIT和ROLLBACK。BEGIN开始一个事务,之后的所有操作都可以取消。COMMIT使BEGIN后的所有命令得到确认;而ROLLBACK还原BEGIN之后的所有操作。如: 
sqlite> BEGIN; 
sqlite> DELETE FROM foods; 
sqlite> ROLLBACK; 
sqlite> SELECT COUNT(*) FROM foods; 
COUNT(*) 
412 
上面开始了一个事务,先删除了foods表的所有行,但是又用ROLLBACK进行了回卷。再执行SELECT时发现表中没发生任何改变。 

SQLite默认情况下,每条SQL语句自成事务(自动提交模式)。 

三、冲突解决 :

如前所述,违反约束会导致事务的非法结束。大多数数据库(管理系统)都是简单地将前面所做的修改全部取消。 
SQLite有其独特的方法来处理约束违反(或说从约束违反中恢复),被称为冲突解决。 
如: 
sqlite> UPDATE foods SET id=800-id; 
SQL error: PRIMARY KEY must be unique 
SQLite提供5种冲突解决方案:REPLACE、IGNORE、FAIL、ABORT和ROLLBACK。 
REPLACE: 当发违反了唯一完整性,SQLite将造成这种违反的记录删除,替代以新插入或修改的新记录,SQL继续执行,不报错。 
IGNORE 
FAIL 
ABORT 
ROLLBACK 

数据库锁 :

在SQLite中,锁和事务是紧密联系的。为了有效地使用事务,需要了解一些关于如何加锁的知识。 
SQLite采用粗放型的锁:
当一个连接要写数据库,所有其它的连接被锁住,直到写连接结束了它的事务。SQLite有一个加锁表,来帮助不同的写数据库都能够在最后一刻再加锁,以保证最大的并发性。 

SQLite使用锁逐步上升机制,为了写数据库,连接需要逐级地获得排它锁。

SQLite有5个不同的锁状态:未加锁(UNLOCKED)共享 (SHARED)保留(RESERVED)未决(PENDING)排它(EXCLUSIVE)。每个数据库连接在同一时刻只能处于其中一个状态。每 种状态(未加锁状态除外)都有一种锁与之对应。 
最初的状态是未加锁状态,在此状态下,连接还没有存取数据库。当连接到了一个数据库,甚至已经用BEGIN开始了一个事务时,连接都还处于未加锁状态。 
未加锁状态的下一个状态是共享状态。为了能够从数据库中读(不写)数据,连接必须首先进入共享状态,也就是说首先要获得一个共享锁。多个连接可以 同时获得并保持共享锁,也就是说多个连接可以同时从同一个数据库中读数据。但哪怕只有一个共享锁还没有释放,也不允许任何连接写数据库。 
如果一个连接想要写数据库,它必须首先获得一个保留锁一个数据库上同时只能有一个保留锁。保留锁可以与共享锁共存,保留锁是写数据库的第1阶段。保留锁即不阻止其它拥有共享锁的连接继续读数据库,也不阻止其它连接获得新的共享锁。 
一旦一个连接获得了保留锁,它就可以开始处理数据库修改操作了,尽管这些修改只能在缓冲区中进行,而不是实际地写到磁盘。对读出内容所做的修改保存在内存缓冲区中。 
当连接想要提交修改(或事务)时,需要将保留锁提升为排它锁。为了得到排它锁,还必须首先将保留锁提升为未决锁。获得未决锁之后,其它连接就不能 再获得新的共享锁了,但已经拥有共享锁的连接仍然可以继续正常读数据库。此时,拥有未决锁的连接等待其它拥有共享锁的连接完成工作并释放其共享锁。 
一旦所有其它共享锁都被释放,拥有未决锁的连接就可以将其锁提升至排它锁,此时就可以自由地对数据库进行修改了。所有以前对缓冲区所做的修改都会被写到数据库文件。


事务的种类 
SQLite有三种不同的事务,使用不同的锁状态。事务可以开始于:DEFERRED、MMEDIATE或EXCLUSIVE。事务类型在BEGIN命令中指定: 

基本的准则:如果你正在使用的数据库没有其它的连接,用BEGIN就足够了。但是,如果你使用的数据库有其它的连接也会对数据库进行写操作,就得使用BEGIN IMMEDIATE或BEGIN EXCLUSIVE开始你的事务。

0 0
原创粉丝点击