daoAndroid开发Android开发经验谈

SQLite事务和锁

2018-03-05  本文已影响26人  carver

SQLite锁机制

SQLite有一个加锁表,用来帮助不同的写数据库都能够在最后一刻加锁,保证最大的并发性。 SQLite有五种不同的锁状态:

SQLite事务

事务定义了一组SQL命令的边界,这组命令或者作为一个整体被全部执行,或者都不执行,这被称为数据库完整性的原子性原则。
默认情况下,SQLite中每条SQL语句自成事务(自动提交模式)。所有成功完成的命令偶都自动提交,所有遇见错误的命令都回滚。

事务属性:

默认情况下,SQLite的每条语句就是一条事务,比如执行一条INSERT语句,执行后,INSERT语句就生效,提交到了数据库中。

SQLite使用以下命令控制事务:

SQLite事务类型

SQLite有三种不同的事务类型:

事务类型在BEGIN命令中指定。

一个deferred事务不获取任何锁,直到它需要锁的时候。而且BEGIN语句本身也不会做什么事情——它开始于UNLOCK状态;默认情况下是这样的。如果仅仅用BEGIN开始一个事务,那么事务就是DEFERRED的,同时它不会获取任何锁,当对数据库进行第一次读操作时,它会获取SHARED LOCK;同样,当进行第一次写操作时,它会获取RESERVED LOCK。

由BEGIN开始的Immediate事务会试着获取RESERVED LOCK。如果成功,BEGIN IMMEDIATE保证没有别的连接可以写数据库。但是,别的连接可以对数据库进行读操作,但是RESERVED LOCK会阻止其它的连接BEGIN IMMEDIATE或者BEGIN EXCLUSIVE命令,SQLite会返回SQLITE_BUSY错误。这时你就可以对数据库进行修改操作,但是你不能提交,当你COMMIT时,会返回SQLITE_BUSY错误,这意味着还有其它的读事务没有完成,得等它们执行完后才能提交事务。

Exclusive事务会试着获取对数据库的EXCLUSIVE锁。这与IMMEDIATE类似,但是一旦成功,EXCLUSIVE事务保证没有其它的连接,所以就可对数据库进行读写操作了。 上面那个例子的问题在于两个连接最终都想写数据库,但是他们都没有放弃各自原来的锁,最终,shared 锁导致了问题的出现。如果两个连接都以BEGIN IMMEDIATE开始事务,那么死锁就不会发生。在这种情况下,在同一时刻只能有一个连接进入BEGIN IMMEDIATE,其它的连接就得等待。BEGIN IMMEDIATE和BEGIN EXCLUSIVE通常被写事务使用。就像同步机制一样,它防止了死锁的产生。 基本的准则是:如果你在使用的数据库没有其它的连接,用BEGIN就足够了。但是,如果你使用的数据库在其它的连接也要对数据库进行写操作,就得使用BEGIN IMMEDIATE或BEGIN EXCLUSIVE开始你的事务

SQLite死锁

SQLite可能会发生死锁。如:

B连接执行INSERT语句时获得了reserved锁,reserved锁只有一个,而且它不会阻止其他连接获取shared锁;A连接执行SELECT语句获得shared锁;此时B连接进行commit,由于shared锁还未释放,B连接无法获得pending锁;A连接执行INSERT语句,想获取reserved锁,但是reserved锁只有一个且被B连接持有,所以A连接等待reserved锁;A连接shared锁一直没有释放,B连接就不能提升到exclusive锁,等待A连接释放shared锁。

使用正确的事务类型可以避免死锁。

一个DEFERRED事务不获取任何锁(直到它需要锁的时候),BEGIN语句本身也不会做什么事情——它开始于UNLOCK状态。默认情况下就 是这样的,如果仅仅用BEGIN开始一个事务,那么事务就是DEFERRED的,同时它不会获取任何锁;当对数据库进行第一次读操作时,它会获取 SHARED锁;同样,当进行第一次写操作时,它会获取RESERVED锁。

由BEGIN开始的IMMEDIATE事务会尝试获取RESERVED锁。如果成功,BEGIN IMMEDIATE保证没有别的连接可以写数据库。但是,别的连接可以对数据库进行读操作;但是,RESERVED锁会阻止其它连接的BEGIN IMMEDIATE或者BEGIN EXCLUSIVE命令,当其它连接执行上述命令时,会返回SQLITE_BUSY 错误。这时你就可以对数据库进行修改操作了,但是你还不能提交,当你 COMMIT时,会返回SQLITE_BUSY错误,这意味着还有其它的读事务没有完成,得等它们执行完后才能提交事务。

EXCLUSIVE事务会试着获取对数据库的EXCLUSIVE锁。这与IMMEDIATE类似,但是一旦成功,EXCLUSIVE事务保证没有其它的连接,所以就可对数据库进行读写操作了。

上一篇下一篇

猜你喜欢

热点阅读