`

关于系统出现The database file is locked错误的说明

阅读更多

在本系统运行中,偶尔会出现奇怪的错误提示,根据后台日志提示,在系统并发比较大的时候,容易出现The database file is locked的错误,具体错误信息在后台log文件的记录如下:
2008-12-19 06:54:59,609 [20] ERROR- 系统出现未处理错误:
System.Data.SQLite.SQLiteException: The database file is locked
database is locked
   在 System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt)
   在 System.Data.SQLite.SQLiteDataReader.NextResult()
   在 System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
   在 System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
   在 LevenBlog.Data.Sqlite.SqliteHelper.ExecuteNonQuery(IDbProvider provider, String sqlString, IDataParameter[] sqlParas)
   在 LevenBlog.Data.Sqlite.SqliteState.Update(IDbProvider provider, lb_state state)
   在 LevenBlog.Service.Mvc.BlogBaseController.OnActionExecuting(ActionExecutingContext filterContext)
   在 System.Web.Mvc.Controller.System.Web.Mvc.IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
   在 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   在 System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassc.<>c__DisplayClasse.<InvokeActionMethodWithFilters>b__b()
   在 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(MethodInfo methodInfo, IDictionary`2 parameters, IList`1 filters)
   在 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)

查了下sqlite的信息,发现Sqlite在并发的情况下确实有一些问题,FAQ的信息如下 :
(7) 多个应用程序或者同一个应用程序的多个例程能同时存取同一个数据库文件吗?

多进程可以同时打开同一个数据库,也可以同时 SELECT 。但只有一个进程可以立即改数据库。

SQLite使用读/写锁定来控制数据库访问。(Win95/98/ME 操作系统缺乏读/写锁定支持,在低于 2.7.0 的版本中,这意味着在 windows 下在同一时间内只能有一个进程读数据库。在版本 2.7.0 中 这个问题通过在 windows 接口代码中执行一个用户间隔几率读写锁定策略解决了。) 但如果数据库文件在一个 NFS 文件系统中,控制并发读书的锁定机制可以会出错。因为 NFS 的fcntl() 文件锁定有时会出问题。如果有多进程可能并发读数据库则因当避免把数据库文件放在 NFS 文件系统中。 根据微软的文档,如果不运行 Share.exe 后台程序则 FAT 文件系统中的锁定可能不工作。对 Windows 非常有经验的人告诉我网络文件的锁定有许多问题并且不可靠。如果是这样,在2个或以上 Windows 系统中共享一个 SQLite 数据库文件会导致不可预知的问题。

我们知道没有其他的嵌入式 SQL数据库引擎比SQLite支持更多的并发性。 SQLite允许多进程 同时打开和读取数据库。任何一个进程需要写入时,整个数据库将在这一过程中被锁定。但这一般仅耗时 几毫秒。其他进程只需等待然后继续其他事务。其他嵌入式SQL数据库引擎往往只允许单进程访问数据库。

但是,client/server型的数据库引擎 (如 PostgreSQL, MySQL, 以及 Oracle) 通常支持更高的并发度, 并支持多进程同时写入同一个数据库。由于总有一个控制良好的服务器协调数据库的访问,这才保证了以上 特性的实现。如果你的应用需要很高的并发度,你应该考虑使用client/server数据库。事实上,经验告诉 我们大多数应用所需要的并发度比他们的设计者们想象的要少得多。

当 SQLite 尝试操作一个被另一个进程锁定的文件时,缺省的行为是返回 SQLITE_BUSY。你可以用 C代码更改这一行为。 使用 sqlite3_busy_handler() 或sqlite3_busy_timeout() API函数。

如果两个或更多进程同时打开同一个数据库,其中一个进程创建了新的表或索引,则其它进程可能不能立即看见新的表。其它进程可能需要关闭并重新连结数据库。


--------------------------------------------------------------------------------

(8) SQLite是线程安全的吗?

有时候是的。为了线程安全,SQLite 必须在编译时把 THREADSAFE 预处理宏设为1。在缺省的发行的已编译版本中 Windows 版的是线程安全的,而 Linux 版的不是。如果要求线程安全,Linux 版的要重新编译。

“线程安全”是指二个或三个线程可以同时调用独立的不同的sqlite3_open() 返回的"sqlite3"结构。而不是在多线程中同时使用同一个 sqlite3 结构指针。

一个sqlite3结构只能在调用 sqlite3_open创建它的那个进程中使用。你不能在一个线程中打开一个数据库然后把指针传递给另一个线程使用。这是因为大多数多线程系统的限制 (或 Bugs?)例如RedHat9上。在这些有问题的系统上,一个 线程创建的fcntl()锁不能由另一个线程删除或修改。由于SQLite依赖fcntl()锁来进行并发控制,当在线程间传递数据库连接时会出现严重的 问题。

也许在Linux下有办法解决fcntl()锁的问题,但那十分复杂并且对于正确性的测试将是极度困难的。因此,SQLite目前不允许在线程间共享句柄。

在UNIX下,你不能通过一个 fork() 系统调用把一个打开的 SQLite 数据库放入子过程中,否则会出错。

因此可以肯定,系统出现lock错误是因为同时2个或者2个以上的线程对数据库执行写操作,本来数据库写入应该在很短的时间内完成,而其他进程也可 以顺序写入数据,但是某些时候老f的服务器可能会资源不够用导致某个写入进程老半天没写入完成而导致其他写入进程超时错误,从而出现了lock的错误.

解决方案:sqlite毕竟是面向嵌入式系统的小型数据库,我们 无法要求它拥有很高的并发能力,因此我们可以考虑在程序上对这个问题进行修正,比如在对写入数据库的操作加锁,使系统可以避免此类错误,当然,更好的选择 是使用SqlServer版的系统,比如51mvc.com就没出现这样的问题.最近没啥时候,而且问题并不严重,看了下出现的几率还是很小的,所以决定 稍等等在修正这个问题.

分享到:
评论

相关推荐

    解决sqlite死锁示例异常database is locked示例

    当出现"database is locked"异常时,通常是因为某个事务在执行时被阻塞,无法完成操作。这可能是由于另一个事务持有相关的锁,并且没有在合理的时间内释放。可以通过日志、调试工具或SQLite的错误信息来识别这种情况...

    sqlite死锁datebaselock解决方案

    在多线程环境下,由于并发操作不当,可能会出现“database is locked”(数据库被锁定)的错误,这通常涉及到SQLite的锁机制和事务处理。本文将深入探讨这个问题,并提供具体的解决方案。 一、SQLite锁机制 SQLite...

    Oracle应用常见傻瓜问题 1000问

    LOGFILE GROUP 1 ('/oracle/oradata/orcl/redo01.log') SIZE 100M; ``` #### 4. Oracle 8.1.7 如何创建数据库? 与Oracle 8.0.5类似,但在8.1.7版本中,可能需要调整某些参数来适应新的特性或者限制。创建过程...

    orcale常用命令

    非特权用户访问时,会出现以下提示: ERROR: ORA-01035: ORACLE 只允许具有 RESTRICTED SESSION 权限的用户使用 6、startup force 强制启动方式 当不能关闭数据库时,可以用startup force来完成数据库的关闭 先...

    Oracle经典问答一览

    Oracle是世界上最广泛使用的数据库管理系统之一,它包含了众多复杂的特性和功能。以下是一些基于Oracle的经典问答,涵盖了数据库的安装、管理、性能优化、安全性等多个方面: 1. **Oracle的初始口令**:在安装完成...

    Oracle数据库管理员笔试题

    Oracle数据库管理员笔试题涉及到多个方面的Oracle知识,涵盖了数据库架构、SGA与PGA、启动与关闭数据库、归档模式、数据导入导出、数据库监控、索引、分区表、Linux系统管理、存储过程、异常处理、操作系统命令、表...

    ZendFramework中文文档

    Querying if the input is valid 14.5.3.2. Getting Invalid, Missing, or Unknown Fields 14.5.3.3. Getting Valid Fields 14.5.4. Using Metacommands to Control Filter or Validator Rules 14.5.4.1. The ...

    Oracle数据库日常维护手册.pdf

    - 需要特别注意备份过程中出现的任何错误或警告。 ##### 5.2 检查BACKUP卷中文件产生的时间 - **操作**:检查备份卷中的文件生成时间。 - 通过比较备份文件的时间戳,可以判断最近一次备份是否已经按计划执行。 ...

    ORACLE 操作指南

    - **参数说明**: - `tablespace_name`: 表空间名称。 - `filespec`: 表空间文件的名称及其完整路径。 - `SizeValue`: 定义表空间初始大小。 - `AUTOEXTEND ON`: 允许表空间自动扩展。 - `NEXT ExtStorage`: ...

Global site tag (gtag.js) - Google Analytics