我们有一个用Classic ASP编写的遗留Web应用程序,它当前使用MS Access数据库作为其数据存储。通过Jet OleDB提供程序与数据库进行交互:
Provider=Microsoft.JET.OLEDB.4.0;Data Source=database.mdb
与大多数Web应用程序一样,CRUD操作定期在数据库上执行。
应用程序连接到数据库,执行insert
,update
,delete
或select
语句,然后关闭连接。在关闭连接后,我们可以重命名或移动 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一样吗?
答案 0 :(得分:2)
使用CH Werner SQLite ODBC Driver,您无法关闭连接池。驱动程序中有代码处理SQL_ATTR_CONNECTION_POOLING
属性,但该属性从未使用过。这意味着默认情况下它将使用连接池。
阻止IIS保持对数据库的锁定将涉及修改DLL以包含 ConnectionPooling = True / False 或 CPTimeout = n ,以便我们可以发送适当的值到SQLSetEnvAttr
函数。