防止 IIS 对 SQLite 数据库文件保持文件锁定

Preventing IIS from keeping a file lock on a SQLite database file

我们有一个用 Classic ASP 编写的遗留 Web 应用程序,目前使用 MS Access 数据库作为其数据存储。通过 Jet OleDB 提供程序与数据库进行交互:

Provider=Microsoft.JET.OLEDB.4.0;Data Source=database.mdb

与大多数 Web 应用程序一样,定期对数据库执行 CRUD 操作。

应用程序连接到数据库,执行insertupdatedeleteselect语句然后关闭连接。在连接关闭后,我们可以立即重命名移动 MS Access .mdb 文件而不受惩罚。多年来,我们一直在利用这种行为 - 这对我们的用例来说是必要的,而且对我们很有帮助。

由于各种原因,我们正在用 SQLite 3 替换 MS Access 数据库。我们通过 ODBC 连接到 SQLite 版本。

与 SQLite 数据库的交互就像以前一样,即连接到数据库,发出 SQL 命令,关闭连接。

问题是 SQLite 数据库文件在连接关闭后保持锁定状态 60 秒。这会阻止我们重命名或移动数据库文件,因为很可能在那 60 秒内发生另一个连接,因此该文件似乎被永久锁定。

我们在经典 ASP 中创建了一个最小页面来说明行为:

Dim connectionString: connectionString = "DRIVER=SQLite3 ODBC Driver;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;FKSupport=0;NoCreat=1;Database=database.sqlite"

Dim con : Set con = CreateObject("ADODB.Connection")
con.Open connectionString

' Issue some CRUD commands here

con.Close
Set con = Nothing
Response.Write("We are here!!!!!")

为了确定导致锁定的原因,我们构建了一个 VBScript 文件(使用上面显示的相同 SQLite 连接字符串)然后我们 运行 从命令行(因此根本不涉及 IIS。)

在那种情况下,在连接、发出任何 CRUD 命令然后关闭数据库后,SQLite 文件可以立即访问。因此我们得出结论,IIS 7.5(或更准确地说 W3WP.exe)以某种方式对 SQLite 文件持有某种锁定。事实上,如果我们停止网站的应用程序池,文件上的锁会立即释放。

VBScript文件的代码如下:

Dim connectionString: connectionString = "DRIVER=SQLite3 ODBC Driver;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;FKSupport=0;NoCreat=1;Database=database.sqlite"

Dim con : Set con = CreateObject("ADODB.Connection")
con.Open connectionString

' Issue some CRUD commands here

WScript.Echo "Press [ENTER] to continue..."

' Read dummy input. This call will not return until [ENTER] is pressed.
WScript.StdIn.ReadLine

WScript.Echo "Done."

con.Close
Set con = Nothing

IIS 中是否有某种设置可供我们使用,使我们能够像目前使用 MS Access 一样操作 SQLite 数据库?

使用 CH Werner SQLite ODBC Driver 您无法关闭连接池。驱动程序中有处理 SQL_ATTR_CONNECTION_POOLING 属性的代码,但从未使用过该属性。这意味着它将默认使用连接池。

停止 IIS 锁定数据库将涉及修改 DLL 以包含 ConnectionPooling=True/FalseCPTimeout=n 这样我们就可以将适当的值发送到 SQLSetEnvAttr 函数。

我在发布原始问题大约一年后重新访问了这个问题,因为一位同事实际上发现了对我们有用的解决方案,也许它会对其他人有所帮助。

有效的解决方案是对注册表进行一些更改。这与 CH Werner SQLIte ODBC Driver 无关。事实上,我们与 CH Werner 本人进行了电子邮件对话,他确认驱动程序不会像我们描述的那样影响数据库的锁定。

解决方法是对注册表进行如下修改:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{c8b522cb-5cf3-11ce-ade5-00aa0044773d}]
@="MSDASQL"
"OLEDB_SERVICES"=dword:fffffffe
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Wow6432Node\CLSID\{c8b522cb-5cf3-11ce-ade5-00aa0044773d}]
@="MSDASQL"
"OLEDB_SERVICES"=dword:fffffffe

如果您将上述注册表更改放入文件扩展名为 .reg 的文件中,您将能够 double-click 在 windows 资源管理器中将其 double-click进行更改。

一旦注册表有了这些设置,IIS 不会 在连接关闭后锁定 SQLite 数据库文件 60 秒。

希望这会帮助遇到此问题的其他人。