SQlite数据库的C编程接口(七)数据库锁定(Database Locking)
by斜风细雨QQ:253786989 2012-02-09
对于《UsingSQLite》的这一节内容,理解的不是很清楚。有时间要仔细看看SQLite的文档:http://www.sqlite.org/lockingv3.html(FileLockingAndConcurrencyInSQLiteVersion3)
SQLite使用一些不同的锁来保护数据库,以允许多个数据库连接同时访问一个相同的数据库文件,而不会出现数据库损坏。不管是在“自动提交事务(autocommittransaction)”模式,还是“显示事务(explicittransaction)”模式,这些锁都工作良好。
SQLite锁系统(lockingsystem)涉及几个不同层次的锁,用来减少竞争、避免死锁等等。以使SQlite允许多个数据库连接并行读取同一个数据库文件,不过任何写操作都需要完整的,整个数据库文件的独占访问。
大部分时间锁系统(lockingsystem)工作良好,允许不同的应用程序之间方便和安全的分享同一个数据库文件。如果编码得当,大部分写操作仅仅需要几分之一秒。然而,如果多个数据库连接试图在同一时间访问同一个数据库文件,那这些操作迟早会相遇。通常情况下,如果一个数据库操作需要一个暂时无法得到的锁,那么SQLite会返回SQLITE_BUSY,或者在更极端的情况下,返回SQLITE_IOERR(或者扩展码SQLITE_IOERR_BLOCKED)。函数sqlite3_prepare_xxx、sqlite3_step、sqlite3_reset、sqlite3_finalize会返回SQLITE_BUSY。函数sqlite3_backup_step、sqlite3_blob_open也会返回SQLITE_BUSY,因为在这两个函数的内部都是通过调用sqlite3_prepare_xxx、sqlite3_step函数来完成工作的。如果调用sqlite3_close函数时,所连接的数据库存在没有销毁(unfinalize)的语句,则该函数也会返回SQLITE_BUSY。
如果想访问某个锁,就需要等待其所有者完成并释放对它的使用,通常不会等待太长时间。等待(waiting)状态可以由应用程序处理,比如接收到SQLITE_BUSY应答,则再次尝试处理该语句。或者也可以由一个忙处理程序(busyhandler)来处理。
忙处理程序(Busyhandlers)
busyhandler(忙处理程序)是一个回调函数,当SQLitelibrary无法获取一个锁时调用。在busyhandler中,可以继续尝试获取锁的操作,或者放弃并返回SQLITE_BUSY错误码。
SQLite有一个内置的基于定时器的busyhandler,可以给这个busyhandler设置一个以毫秒为单位的超时时间。在超时时间范围内,busyhandler将继续重复尝试获取锁的操作。
- intsqlite3_busy_timeout(sqlite3*,intms);
int sqlite3_busy_timeout(sqlite3*, int ms);
用来设置内置busyhandler的超时时间,以毫秒为单位。如果给ms参数传递0或者负值,则内置的busyhandler被清除。
程序员也可以自己写busyhandler,然后通过aqlite3_busy_handler函数进行设置。
- intsqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
给指定的数据库连接设置自定义的busyhandler,把自己写的busyhandler函数传递给该函数的第2个参数。如果给第2个参数传递NULL,则移除自定义的busyhandler。第3个参数是传递给busyhandler回调函数的用户数据指针。
自定义的busyhandler回调函数原型如下:
- intuser_defined_busy_handler_callback(void*udp,intincr)
int user_defined_busy_handler_callback( void *udp, int incr )
第1个参数是通过sqlite3_busy_handler函数传递过来的用户数据指针。第2个参数是一个计数器,每次busyhandler被调用时该计数器的计数递增。如果该回调函数返回0,则SQLite将放弃获取锁的操作,并返回SQLITE_BUSY。如果该函数返回一个非0值,则SQLite将继续尝试获取锁的操作。
需要注意的是:一个数据库连接仅仅可以拥有一个busyhandler,不能同时设置自定义的busyhandler并配置内置的基于定时器的busyhandler。每次设置其中一种busyhandler都将删除另一个busyhandler。
死锁(Deadlocks)
为一个数据库连接设置busyhandler不能够解决所有问题。有的时候在多个数据库连接之间会出现死锁现象。比如两个数据库连接各自持有一些锁,但是它们现在都在等待对方持有的锁被释放,这样就会造成死锁现象。唯一的解决办法,就是其中一个数据库连接放弃获取锁的操作,并释放自己所持有的锁。
如果SQLite检测到了一个潜在的死锁情况,它将跳过busyhandler,并将有一个数据库连接立刻返回SQLITE_BUSY。这样做是为了鼓励应用程序释放他们自己的锁,以打破死锁现象。
避免SQLITE_BUSY(AvoidingSQLITE_BUSY)
如果我们在开发某个项目时需要充分考虑数据库的并发性能,最简单的方法是使用sqlite3_busy_timeout设置内置的busyhandler,并且超时时间在250-2000毫秒范围内进行调整,这样可以减少SQLITE_BUSY的产生。
如果想完全避免SQLITE_BUSY,唯一的办法就是确保对于同一个数据库某一个时刻仅仅存在一个数据库连接。这需要设置PRAGMAlocking-mode为EXCLUSIVE(独占的)。
另外,应用程序可以使用独占模式(EXCLUSIVE)的事务,这样对于SQLITE_BUSY返回值的处理就更容易些。可以通过BEGINEXCLUSIVETRANSACTION命令开启一个独占式的事务,如果成功则在事务的执行过程中不会返回SQLITE_BUSY。不过BEGIN命令本身可能会执行失败并返回SQLITE_BUSY,但这种情况处理起来很容易,应用程序可以通过sqlite3_reset函数重置BEGIN语句,然后重试。BEGINEXCLUSIVE的缺点是只有目前没有其他的数据库连接(包括只读事务)正在访问该数据库,它才会执行成功。而且一旦独占式的事务开始执行,它同样会锁住数据库,使其他的数据库连接(包括只读事务)无法访问该数据库。
为了允许更多的并发访问,还有一种类型的事务——IMMEDIATETRANSACTION(即时事务)。可以通过BEGINIMMEDIATETRANSACTION命令启动一个即时事务,如果成功则在事务执行的过程中通常只有执行到COMMIT语句时才会返回SQLITE_BUSY。不管是事务中的哪些命令(包括COMMIT),一旦遇到了SQLITE_BUSY,应用程序可以简单的重置语句然后等待并重试。BEGINIMMEDIATE语句本身也有可能会遭遇SQLITE_BUSY,这时应用程序也是可以简单的重置BEGIN语句然后重试。与EXCLUSIVETRANSACTION不同的是,如果存在其它的数据库连接正在读取(非写)数据库,这时候IMMEDIATE事务是可以启动的。一旦IMMEDIATE事务成功启动,则不允许其它数据库连接进行写入操作,但只读的数据库连接仍然可以访问数据库,除非IMMEDIATE事务正在强制修改数据库文件(通常是事务正在执行COMMIT操作)。使用IMMEDIATE事务不会发生死锁现象,所有的SQLITE_BUSY可以通过重试操作进行处理。
避免死锁(Avoidingdeadlocks)
避免死锁的原则比较简单,不过遵循这些原则会使应用程序变得复杂一些。
首先,sqlite3_prepare_xxx、sqlite3_backup_step、sqlite3_blob_open函数调用不会产生死锁现象。任何时候如果这些函数返回SQLITE_BUSY,简单的等待一下然后重试即可。
如果在一个(deferred)事务中,sqlite3_step、sqlite3_reset、sqlite3_finalize函数返回SQLITE_BUSY,则应用程序必须回退然后重试。如果这些语句不在一个显示的(explicit)事务中,prepared语句可以简单的重置然后重新执行。如果这些语句在一个显示的(explicit)事务中,那么整个事务就必须回退,然后从头开始执行。致使回退的整个原因就是其他一些数据库连接需要修改数据库。另外需要注意的是,如果应用程序完成了一些读取操作并准备进行写操作,那么在新的事务中最好重新读取这些信息以确定这些数据仍然有效。
不管你做什么,不要忽视SQLITE_BUSY。它可能很少发生,但如果处理不当它就可能成为大麻烦的源头。
当“繁忙”转换为“被阻塞”(WhenBUSYbecomesBLOCKED)
当一个连接需要修改数据库中的数据,数据库就要被加锁使其对于其他连接处于只读状态。事实上,事务中对于数据库的某个修改并没有马上写入数据库文件,而是保存在数据库的页缓存中。因为如果将这个修改直接写入数据库,那么这个修改对于其他的读连接就可见了,这就打破了事务的隔离性原则。
当所有需要的修改操作全部做完,事务开始准备提交。这时数据库文件会被进一步锁定,不允许新的只读事务启动。允许已经存在的读操作(reader)完成,并释放他们持有的数据库锁。当所有的读操作完成,写操作(writer)就要独占式的访问数据库,最终将页缓存中的修改刷新到数据库中。
这一过程允许写事务正在执行的同时,只读事务依然可以继续运行。当写事务确实在提交数据时,读事务被锁定。然而,一个关键的假设是在这个过程中,所有修改被放入页缓存中,直到事务提交的时候才被写入数据库。如果缓存(cache)中装满了(包含处于悬挂状态的修改的)数据页,那么写事务没有其它选择,只能给数据库加一个独占锁,并且在提交(commit)阶段之前刷新缓存。该事务仍然可以在任何时候回滚,但是写入操作必须获得独占锁的即时访问,以刷新缓存。
如果这个锁不是立即可用,写入操作就会被强制终止整个事务。写入事务将回退,然后返回扩展码SQLITE_IOERR_BLOCKED。因为事务是自动回退的,所以应用程序没有更多选择,只能重新启动事务。
为了避免这种情况,最好是用显示的BEGINEXCLUSIVE语句启动一个可以修改多行数据的大事务。BEGINEXCLUSIVE也许会失败,并返回SQLITE_BUSY,但是应用程序可以简单的重新尝试直到成功。一旦一个独占式的事务成功启动,它就可以完整的访问数据库,消除SQLITE_IOERR_BLOCKED的出现,甚至事务在提交之前就造成了缓冲区溢出(增加数据库缓存会有所帮助)。
SQlite数据库的C编程接口(七)数据库锁定(Database Locking)
by斜风细雨QQ:253786989 2012-02-09
SQlite数据库的C编程接口(七)数据库锁定(Database Locking)
by斜风细雨QQ:253786989 2012-02-09
对于《UsingSQLite》的这一节内容,理解的不是很清楚。有时间要仔细看看SQLite的文档:http://www.sqlite.org/lockingv3.html(FileLockingAndConcurrencyInSQLiteVersion3)
SQLite使用一些不同的锁来保护数据库,以允许多个数据库连接同时访问一个相同的数据库文件,而不会出现数据库损坏。不管是在“自动提交事务(autocommittransaction)”模式,还是“显示事务(explicittransaction)”模式,这些锁都工作良好。
SQLite锁系统(lockingsystem)涉及几个不同层次的锁,用来减少竞争、避免死锁等等。以使SQlite允许多个数据库连接并行读取同一个数据库文件,不过任何写操作都需要完整的,整个数据库文件的独占访问。
大部分时间锁系统(lockingsystem)工作良好,允许不同的应用程序之间方便和安全的分享同一个数据库文件。如果编码得当,大部分写操作仅仅需要几分之一秒。然而,如果多个数据库连接试图在同一时间访问同一个数据库文件,那这些操作迟早会相遇。通常情况下,如果一个数据库操作需要一个暂时无法得到的锁,那么SQLite会返回SQLITE_BUSY,或者在更极端的情况下,返回SQLITE_IOERR(或者扩展码SQLITE_IOERR_BLOCKED)。函数sqlite3_prepare_xxx、sqlite3_step、sqlite3_reset、sqlite3_finalize会返回SQLITE_BUSY。函数sqlite3_backup_step、sqlite3_blob_open也会返回SQLITE_BUSY,因为在这两个函数的内部都是通过调用sqlite3_prepare_xxx、sqlite3_step函数来完成工作的。如果调用sqlite3_close函数时,所连接的数据库存在没有销毁(unfinalize)的语句,则该函数也会返回SQLITE_BUSY。
如果想访问某个锁,就需要等待其所有者完成并释放对它的使用,通常不会等待太长时间。等待(waiting)状态可以由应用程序处理,比如接收到SQLITE_BUSY应答,则再次尝试处理该语句。或者也可以由一个忙处理程序(busyhandler)来处理。
忙处理程序(Busyhandlers)
busyhandler(忙处理程序)是一个回调函数,当SQLitelibrary无法获取一个锁时调用。在busyhandler中,可以继续尝试获取锁的操作,或者放弃并返回SQLITE_BUSY错误码。
SQLite有一个内置的基于定时器的busyhandler,可以给这个busyhandler设置一个以毫秒为单位的超时时间。在超时时间范围内,busyhandler将继续重复尝试获取锁的操作。
- intsqlite3_busy_timeout(sqlite3*,intms);
int sqlite3_busy_timeout(sqlite3*, int ms);
用来设置内置busyhandler的超时时间,以毫秒为单位。如果给ms参数传递0或者负值,则内置的busyhandler被清除。
程序员也可以自己写busyhandler,然后通过aqlite3_busy_handler函数进行设置。
- intsqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
给指定的数据库连接设置自定义的busyhandler,把自己写的busyhandler函数传递给该函数的第2个参数。如果给第2个参数传递NULL,则移除自定义的busyhandler。第3个参数是传递给busyhandler回调函数的用户数据指针。
自定义的busyhandler回调函数原型如下:
- intuser_defined_busy_handler_callback(void*udp,intincr)
int user_defined_busy_handler_callback( void *udp, int incr )
第1个参数是通过sqlite3_busy_handler函数传递过来的用户数据指针。第2个参数是一个计数器,每次busyhandler被调用时该计数器的计数递增。如果该回调函数返回0,则SQLite将放弃获取锁的操作,并返回SQLITE_BUSY。如果该函数返回一个非0值,则SQLite将继续尝试获取锁的操作。
需要注意的是:一个数据库连接仅仅可以拥有一个busyhandler,不能同时设置自定义的busyhandler并配置内置的基于定时器的busyhandler。每次设置其中一种busyhandler都将删除另一个busyhandler。
死锁(Deadlocks)
为一个数据库连接设置busyhandler不能够解决所有问题。有的时候在多个数据库连接之间会出现死锁现象。比如两个数据库连接各自持有一些锁,但是它们现在都在等待对方持有的锁被释放,这样就会造成死锁现象。唯一的解决办法,就是其中一个数据库连接放弃获取锁的操作,并释放自己所持有的锁。
如果SQLite检测到了一个潜在的死锁情况,它将跳过busyhandler,并将有一个数据库连接立刻返回SQLITE_BUSY。这样做是为了鼓励应用程序释放他们自己的锁,以打破死锁现象。
避免SQLITE_BUSY(AvoidingSQLITE_BUSY)
如果我们在开发某个项目时需要充分考虑数据库的并发性能,最简单的方法是使用sqlite3_busy_timeout设置内置的busyhandler,并且超时时间在250-2000毫秒范围内进行调整,这样可以减少SQLITE_BUSY的产生。
如果想完全避免SQLITE_BUSY,唯一的办法就是确保对于同一个数据库某一个时刻仅仅存在一个数据库连接。这需要设置PRAGMAlocking-mode为EXCLUSIVE(独占的)。
另外,应用程序可以使用独占模式(EXCLUSIVE)的事务,这样对于SQLITE_BUSY返回值的处理就更容易些。可以通过BEGINEXCLUSIVETRANSACTION命令开启一个独占式的事务,如果成功则在事务的执行过程中不会返回SQLITE_BUSY。不过BEGIN命令本身可能会执行失败并返回SQLITE_BUSY,但这种情况处理起来很容易,应用程序可以通过sqlite3_reset函数重置BEGIN语句,然后重试。BEGINEXCLUSIVE的缺点是只有目前没有其他的数据库连接(包括只读事务)正在访问该数据库,它才会执行成功。而且一旦独占式的事务开始执行,它同样会锁住数据库,使其他的数据库连接(包括只读事务)无法访问该数据库。
为了允许更多的并发访问,还有一种类型的事务——IMMEDIATETRANSACTION(即时事务)。可以通过BEGINIMMEDIATETRANSACTION命令启动一个即时事务,如果成功则在事务执行的过程中通常只有执行到COMMIT语句时才会返回SQLITE_BUSY。不管是事务中的哪些命令(包括COMMIT),一旦遇到了SQLITE_BUSY,应用程序可以简单的重置语句然后等待并重试。BEGINIMMEDIATE语句本身也有可能会遭遇SQLITE_BUSY,这时应用程序也是可以简单的重置BEGIN语句然后重试。与EXCLUSIVETRANSACTION不同的是,如果存在其它的数据库连接正在读取(非写)数据库,这时候IMMEDIATE事务是可以启动的。一旦IMMEDIATE事务成功启动,则不允许其它数据库连接进行写入操作,但只读的数据库连接仍然可以访问数据库,除非IMMEDIATE事务正在强制修改数据库文件(通常是事务正在执行COMMIT操作)。使用IMMEDIATE事务不会发生死锁现象,所有的SQLITE_BUSY可以通过重试操作进行处理。
避免死锁(Avoidingdeadlocks)
避免死锁的原则比较简单,不过遵循这些原则会使应用程序变得复杂一些。
首先,sqlite3_prepare_xxx、sqlite3_backup_step、sqlite3_blob_open函数调用不会产生死锁现象。任何时候如果这些函数返回SQLITE_BUSY,简单的等待一下然后重试即可。
如果在一个(deferred)事务中,sqlite3_step、sqlite3_reset、sqlite3_finalize函数返回SQLITE_BUSY,则应用程序必须回退然后重试。如果这些语句不在一个显示的(explicit)事务中,prepared语句可以简单的重置然后重新执行。如果这些语句在一个显示的(explicit)事务中,那么整个事务就必须回退,然后从头开始执行。致使回退的整个原因就是其他一些数据库连接需要修改数据库。另外需要注意的是,如果应用程序完成了一些读取操作并准备进行写操作,那么在新的事务中最好重新读取这些信息以确定这些数据仍然有效。
不管你做什么,不要忽视SQLITE_BUSY。它可能很少发生,但如果处理不当它就可能成为大麻烦的源头。
当“繁忙”转换为“被阻塞”(WhenBUSYbecomesBLOCKED)
当一个连接需要修改数据库中的数据,数据库就要被加锁使其对于其他连接处于只读状态。事实上,事务中对于数据库的某个修改并没有马上写入数据库文件,而是保存在数据库的页缓存中。因为如果将这个修改直接写入数据库,那么这个修改对于其他的读连接就可见了,这就打破了事务的隔离性原则。
当所有需要的修改操作全部做完,事务开始准备提交。这时数据库文件会被进一步锁定,不允许新的只读事务启动。允许已经存在的读操作(reader)完成,并释放他们持有的数据库锁。当所有的读操作完成,写操作(writer)就要独占式的访问数据库,最终将页缓存中的修改刷新到数据库中。
这一过程允许写事务正在执行的同时,只读事务依然可以继续运行。当写事务确实在提交数据时,读事务被锁定。然而,一个关键的假设是在这个过程中,所有修改被放入页缓存中,直到事务提交的时候才被写入数据库。如果缓存(cache)中装满了(包含处于悬挂状态的修改的)数据页,那么写事务没有其它选择,只能给数据库加一个独占锁,并且在提交(commit)阶段之前刷新缓存。该事务仍然可以在任何时候回滚,但是写入操作必须获得独占锁的即时访问,以刷新缓存。
如果这个锁不是立即可用,写入操作就会被强制终止整个事务。写入事务将回退,然后返回扩展码SQLITE_IOERR_BLOCKED。因为事务是自动回退的,所以应用程序没有更多选择,只能重新启动事务。
为了避免这种情况,最好是用显示的BEGINEXCLUSIVE语句启动一个可以修改多行数据的大事务。BEGINEXCLUSIVE也许会失败,并返回SQLITE_BUSY,但是应用程序可以简单的重新尝试直到成功。一旦一个独占式的事务成功启动,它就可以完整的访问数据库,消除SQLITE_IOERR_BLOCKED的出现,甚至事务在提交之前就造成了缓冲区溢出(增加数据库缓存会有所帮助)。
SQlite数据库的C编程接口(七)数据库锁定(Database Locking)
by斜风细雨QQ:253786989 2012-02-09
分享到:
相关推荐
内容概要:这是一个通过显式调用(dlopen)方式,使用SQLite库API函数C语言编程的demo示例。里面包含了SQLite数据库文件的创建、数据库表创建、插入、修改、删除、查询等功能操作。该资源包中的程序有在Ubuntu环境下...
标题“基于Qt4的SQLite数据库应用编程”揭示了文档将要介绍的知识点,即如何在Qt4框架下进行SQLite数据库的应用编程。从描述中我们知道,Qt是一个由挪威TrollTech公司开发的C++图形用户界面应用程序框架,支持跨平台...
### 基于Qt4的SQLite数据库应用编程 #### 概述 《基于Qt4的SQLite数据库应用编程》是一篇详细介绍如何在Qt4框架下利用SQLite数据库进行应用程序开发的技术文章。作者潘学文和文汉云来自长江大学计算机科学学院,...
这是一个使用C#开发的Sqlite数据库创建、操作的源码工程,关于Sqlite的所有操作已经单独创建了专门的跨平台【.NETCore3.1】类库包含相应的帮助类,可以直接生成后拿到任何项目中直接使用,高效简单,省去了从头开发...
Android SQLite 数据库操作报告 一、实验目的 Android 实验报告的主要目的是熟悉 Android 平台的文件操作、掌握 Android SQLite 数据库的设计和应用、熟悉 XML 和 JSON 文件的读取。通过本实验,用户可以掌握 ...
在VB6.0中操作SQLite数据库,是一种将轻量级、高性能的SQLite数据库与传统的Visual Basic编程环境相结合的方法。SQLite是一种自包含、无服务器、零配置、事务性的SQL数据库引擎,广泛应用于移动设备、嵌入式系统以及...
SQLite数据库是一种轻量级、自包含的SQL数据库引擎,常被用在嵌入式系统和移动应用中。在处理敏感数据时,为了保护信息安全,对SQLite数据库进行加密是必要的步骤。本文将详细介绍如何使用.NET环境下的SQLite加密...
Delphi版SQLite数据库工具是一款专为开发者设计的实用软件,主要用于在Delphi编程环境中与SQLite数据库进行交互。SQLite是一款轻量级、自包含的数据库引擎,广泛应用于嵌入式系统和移动应用,因其高效性和无需服务器...
1. **Web SQL Database**(不推荐):这是W3C曾经提出的一个标准,允许在Web应用中使用SQLite数据库。开发者可以通过SQL语法直接操作数据库。但请注意,这个标准已被废弃,不再推荐使用。 2. **IndexedDB**:这是一...
在Android开发中,SQLite是一个非常重要的组成部分,它是一个轻量级的、开源的、嵌入式的SQL数据库引擎,被广泛用于处理应用程序中的数据存储。"实验十 使用SQLite数据库存储数据"是一个旨在帮助开发者掌握如何在...
SQLite是一款轻量级的、开源的、自包含的SQL数据库引擎,它不需要单独的服务器进程,可以直接嵌入到各类应用程序中。SQLite具有高度移植性,支持多种操作系统和编程语言,如Windows、Linux、Mac OS、Java、C++、...
SQlite数据库工具 供比较两个SQLite数据库所用。
SQLite数据库是一种轻量级、开源的嵌入式关系数据库,广泛应用于移动应用、小型桌面应用以及需要快速存储和检索数据的任何系统。SQLiteBrowser是一款免费且开源的图形用户界面工具,用于浏览、编辑和管理SQLite...
SQLite数据库逆向分析 SQLite数据库逆向分析是一门复杂的技术领域,涉及到软件逆向分析、数据库逆向分析、反汇编、反编译等技术领域。以下为本节课的知识点总结: 1. SQLite数据库逆向分析简介 SQLite数据库逆向...
在使用SQLite数据库进行查询操作时,遇到中文乱码问题,通常是由于编码设置不正确或数据存储与读取过程中编码不一致导致的。SQLite本身支持多种字符编码,包括UTF-8、UTF-16等,但在实际应用中,如果没有正确配置,...
此外,因为SQLite支持多种编程语言的接口,如Python、Java、C#等,所以可以方便地将这个数据库集成到各种软件项目中。 为了进一步处理和分析这些数据,你可能需要了解如何使用SQLite命令行工具,或者在编程环境中...
SQLite是一款轻量级的、开源的、嵌入式的关系型数据库管理系统,广泛应用于移动...通过阅读这份文档,你可以深入理解这两个方法的工作原理,并根据自己的项目需求选择合适的方法来优化SQLite3数据库的磁盘空间使用。
这个压缩包文件"Android源码——数据库SQLite.zip"可能包含了关于Android中SQLite数据库的源码分析、使用示例以及相关的图像资源,如1-120912223R80-L.png,可能用于解释或展示SQLite在Android中的工作原理。...
前情提要:Android 数据库(SQLite) 【简介、创建、使用(增删改查、事务、实战演练)、数据显示控件(ListView、Adapter、实战演练)】 https://blog.csdn.net/weixin_44949135/article/details/105955663 Android ...
SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。 就像其他数据库,SQLite 引擎不是一个...