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

时间:2017-03-17 15:16:22

标签: sqlite ms-access iis asp-classic odbc

我们有一个用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秒内发生了另一个连接,因此文件似乎永久锁定。

我们在Classic 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中的某种设置来操作SQLite数据库,就像我们目前使用MS Access一样吗?

1 个答案:

答案 0 :(得分:2)

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

阻止IIS保持对数据库的锁定将涉及修改DLL以包含 ConnectionPooling = True / False CPTimeout = n ,以便我们可以发送适当的值到SQLSetEnvAttr函数。