SQLite的教程(十二):锁定和并发控制的细节

SQLite的教程(十二):锁定和并发控制的细节
1。总结:

在SQLite,锁定和并发控制机制的pager_module模块处理,如酸(原子性、一致的,孤立的,耐用),事务中包含的数据修改,该模块将确保所有的数据修改提交,或都回滚。同时,该模块还提供了一些磁盘文件内存缓存功能

事实上,这pager_module模块不关心数据库存储的细节,如树、编码方式等指标,只是把它作为一个单一的文件组成的均匀大小的数据块(通常是1024字节),每个被称为一个页面(page)。在这个模块的页面起始号码是1,也就是第一页的索引值是1,和随后的页面数是相同的。
两。文件锁:

在SQLite的当前版本,以下提供的文件锁定状态的五种方法

1)。解锁:

该文件不包含任何锁,也就是说,当前数据库没有任何读或写操作。其他进程可以在数据库上执行任意读写操作。

2)。共享:

在这种状态下,数据库可以被读取,但不能被写入。同时,可以在同一数据库上持有共享锁的任意数量的进程,因此读操作是并发的。换句话说,只要在活动状态中有一个或多个共享锁,则不再允许具有数据库文件的操作。

3)。保留:

如果一个进程试图执行写操作在当前的数据库在未来一段时间,但是,在这个时候,数据是从数据库中读取,然后我们可以简单理解,数据库文件已经保留锁在这个时候。当保留锁处于活跃状态,只有一个或一个以上的共享锁存在于数据库中,即只有一个保留锁和多个共享锁同时存在在同一个数据库。在奥拉克尔,这种锁被称为预写锁。不同之处在于Oracle中的锁粒度可以细化为表甚至行。所以锁定在Oracle的效果不一样,SQLite作为大。

4)。悬而未决的:

未决锁意味着进程将在数据库上执行写操作,但是数据库有很多共享锁(读),然后写操作必须处于等待状态,即等待所有共享锁关闭,同时,新的读操作将不再被允许。为了防止饥饿的写锁现象,在等待期间,数据库文件的锁定状态处于等待状态。在所有共享锁消失后,未决锁状态的数据库文件在获得独占锁后进入独占状态。

5)。独家:

在执行写操作的过程,首先必须获得对数据库的独占锁。但是,只要他有独占锁,没有其他类型的锁可以与之共存。因此,为了最大限度地提高并行效率,SQLite会减少,独家持有锁的时间总量。
最后,与其他关系数据库相比,如Oracle,MySQL,SQLite数据库,所有的数据都存储在同一文件中,同时,它提供的只是一个粗糙的文件锁定,因此,在并发性和可扩展性方面与其他关系数据库SQLite或无法比拟的。可以看出,SQLite的自己的应用场景。例如,在本系列的开头部分中,它与其他关系数据库之间的互换性非常有限。

三。Rollback log:

当一个进程要改变数据库文件,它第一次记录不变的内容在回滚日志文件。如果在SQLite事务试图修改多个数据库中的数据,然后每个数据库将生成一个自己的回滚日志文件,用来记录自己的数据变化,同时产生一个主数据库日志文件的多个数据库操作的协调,包括各种数据库回滚日志文件的名称在主数据库日志文件将在每个回滚日志文件也包含主数据库日志文件的信息。但是,对于一个没有主数据库日志文件回滚日志文件,它会保留主数据库日志文件的信息,但是信息的值为空时。

我们可以看到回滚日志的热的日志文件,因为它存在恢复数据库的一致性。当一个进程正在更新数据库,应用程序或操作系统突然崩溃,更新操作无法顺利完成。所以我们可以说,热的日志只会在特殊的条件下产生的,如果一切都很顺利,该文件将不存在。

四。数据写入:

如果一个进程要对数据库进行写操作,必须首先获得一个共享锁,并保留锁后获得的共享锁获得。因为保留锁表明过程会在将来的某个时间执行写操作,所以只有一个进程可以同时持有保留锁,但其他进程可以继续持有共享锁来完成数据的读取操作。如果进程执行写操作不能得到保留锁,这表明另一个进程获得了保留锁。在这种情况下,失败并立即返回sqlite_busy错误写操作将保留的一个锁。收购成功后,写的过程将产生吃了一个回滚日志。

在更改任何数据写入过程之前,将修改内容页首先写入回滚日志文件,但是,这些数据起初会改变页面,不会直接写入磁盘文件,而是保存在内存中,以便其他进程可以继续读取数据库中的数据。

或是因为内存缓存已满,或申请已提交的事务,并写入程序更新数据库文件的数据。但是,在那之前,写作过程中必须确保没有其他进程在读取数据库,并在回滚日志的数据确实是物理写入磁盘文件。

1)。确保将所有回滚日志数据物理写入磁盘文件,以便在系统崩溃时将数据库恢复到一致状态。

2)。获取挂起的锁并获得独占锁。如果其他进程同时持有共享锁,则写入线程必须挂起并等待共享锁消失,以便获得独占锁。

3)。将保存在内存中的修改页写入原始磁盘文件中。

如果写入数据库文件的原因是因为缓存已满,写进程将不会立即提交,但将继续修改其他页面。但在接下来的修改写入数据库文件,回滚日志必须向磁盘写入了。也要注意写的过程中获得互斥锁必须保持到所有的改变都是提交重要。这也意味着,其他进程无法直到数据刷新到磁盘文件第一直到提交事务访问数据库。

当编写过程准备提交时,遵循以下步骤

4)。获取独占锁并确保内存中的所有更改数据写入磁盘文件中。

5)。所有数据库文件的更改数据被物理写入磁盘。

6)。删除日志文件。如果在删除之前发生系统故障,那么在下次打开数据库时,该过程仍将基于热恢复操作的日志。因此,只有在成功删除日志文件之后,才能想到事务的成功完成。

7)。从数据库文件中删除所有的独占锁和挂起的锁。

一旦挂起的锁被释放,其他进程就可以再次读取数据库。

如果一个事务包含多个数据库修改,那么它的提交逻辑将更加复杂,请参见以下步骤:

4)。确保每个数据库文件都有独占锁和有效日志文件。

5)。创建主数据库日志文件,并将每个数据库的回滚日志文件的文件名写入主数据库日志文件中。

6)。然后,将主数据库日志文件的文件名写入每个数据库回滚日志文件的指定位置

7)。将所有数据库更改持久化到数据库磁盘文件。

8)删除主日志文件。如果删除之前存在系统故障,那么在下次打开数据库时,该进程仍将基于热日志恢复操作。因此,只有在成功删除主日志文件之后,才能想到事务的成功完成。

9)。删除每个数据库的相应日志文件。

10)。从所有数据库中删除锁和挂起的锁。
最后,在sqlite2,如果一个进程是从数据库读取数据,数据库总是读操作,即共享锁在数据库中的每个时刻都至少有一个,这将导致没有过程可以写操作执行,因为在数据库中保存当读锁是无法获得一个写锁,我们将其称之为饥饿。在使用sqlite3,待锁,有效避免发生写饥饿。当一个进程持有等待锁,读操作已经存在可以继续进行,直到正常结束,但新的读操作将不被接受SQLite,所以读操作已经全部结束,抱着一个等待锁的过程可以激活并试图获取排他锁完成数据修改操作。
五,SQL级事务控制:

SQLite3是锁定和并发控制的实现做一些聪明的变化,特别是对交易的SQL语言水平。默认情况下,程序将所有的SQL操作在antocommit模式,那么所有的数据库的修改操作将自动提交的SQL命令执行后,SQLite的SQL命令开始交易用于声明一个交易明确,即后来的SQL语句执行后不会自动提交,但需要等到SQL命令或承诺执行回滚,然后考虑是否提交或回滚。可以推断,该开始执行命令后,没有任何类型的锁立即获得,但当第一个SELECT语句被执行时,得到的是一个共享锁,或保留锁时得到的第一个DML语句被执行。至于行锁,只有当数据写入内存磁盘,行锁可以保持到事务提交或回滚。

如果多个SQL命令的执行在同一个数据库连接的同时,自动提交将被推迟,直到最后一个命令完成。例如,如果执行SELECT语句,该订单的执行过程中,需要将所有检索到的记录,如果结果设置线程由于业务逻辑需要暂时停止和等待状态,而另一个是在这个时候,也许在插入实现螺纹连接,数据库的更新或删除命令,然后这些命令作出的修正数据将要等到选择检索结束后可以提交。

这是关于SQLite的系列理论和应用上的博客。之后,我们将发布两博客如何使用SQLite数据库编程,包括四种典型应用实例代码。

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部