Sqlite 保持连接打开 (Mono.Data.Sqlite.dll)
Sqlite leaves connection open (Mono.Data.Sqlite.dll)
我正在使用这个库使用 mono 查询 sqlite 数据库:
https://www.mono-project.com/docs/database-access/providers/sqlite/
这就是我使用图书馆的方式:
var dbLocation = "/var/log/asterisk/master.db";
var conString = $"Data Source={dbLocation}; Read Only=True; Pooling=True;";
using (var sqlite3 = new Mono.Data.Sqlite.SqliteConnection(conString)
{
try
{
sqlite3.Open();
// query database
using(var command = sqlite3.CreateCommand()){
command.CommandText = "select * from foo";
var reader = command.ExecuteReader();
// etc...
reader.Close(); // close reader
}
}
catch
{
// log error
}
}
注意这段代码每秒执行一次。另一个进程 (Asterisk) 正在写入数据库,而我的进程正在从数据库中读取。我不能让连接保持打开状态,因为如果我这样做,Asterisk 将无法写入该数据库;因此,每次我计划查询数据库时,我都必须打开和关闭连接。
这段代码效果很好!我能够以只读模式查询数据库。我基于此 link:
创建了连接字符串
http://docs.go-mono.com/?link=T%3aMono.Data.Sqlite.SqliteConnection
此代码运行良好,但 2 天后我的程序崩溃了,因为 sqlite.dll 没有正确处理连接。 sqlite.dll 让连接保持打开状态,证据如下:
我的应用程序的进程 ID 是 29140:
然后我 运行 命令 lsof -a -p 29140
然后 returns 我是这样的:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Main 29140 root cwd DIR 8,1 4096 46137345 /root
Main 29140 root rtd DIR 8,1 4096 2 /
Main 29140 root txt REG 8,1 3845024 12586404 /usr/bin/mono-sgen
Main ........
... etc
.... etc
Main 29140 root 74r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 75r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 76r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 77r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 78r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 79r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 80r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 81r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 82r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 83r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 84r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 85r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
因为我每秒都查询数据库,所以我希望每秒创建一个 "file lock" 到 /var/log/asterisk/master.db
。这种情况 运行 经常发生!如果数据库被大量使用,我会看到 /var/log/asterisk/master.db
的数量增加。如何正确处理此 sqlite 连接?
我尝试过的事情:
调用 GC.Collect()
和 GC.WaitForPendingFinalizers()
作为这个答案的建议:
我将连接字符串更改为:(Poling=False)
var conString = $"Data Source={dbLocation}; Read Only=True; Pooling=False;";
我也关闭了我的 reader 作为:
// using very important!
using(var command = sqlite3.CreateCommand())
{
command.CommandText = "select * from foo";
var reader = command.ExecuteReader();
// etc...
reader.Close(); // close reader! <----- this is very important for some reason
}
这已经 运行 一小时了,计数没有增加。我希望这是解决方案。
我正在使用这个库使用 mono 查询 sqlite 数据库:
https://www.mono-project.com/docs/database-access/providers/sqlite/
这就是我使用图书馆的方式:
var dbLocation = "/var/log/asterisk/master.db";
var conString = $"Data Source={dbLocation}; Read Only=True; Pooling=True;";
using (var sqlite3 = new Mono.Data.Sqlite.SqliteConnection(conString)
{
try
{
sqlite3.Open();
// query database
using(var command = sqlite3.CreateCommand()){
command.CommandText = "select * from foo";
var reader = command.ExecuteReader();
// etc...
reader.Close(); // close reader
}
}
catch
{
// log error
}
}
注意这段代码每秒执行一次。另一个进程 (Asterisk) 正在写入数据库,而我的进程正在从数据库中读取。我不能让连接保持打开状态,因为如果我这样做,Asterisk 将无法写入该数据库;因此,每次我计划查询数据库时,我都必须打开和关闭连接。
这段代码效果很好!我能够以只读模式查询数据库。我基于此 link:
创建了连接字符串http://docs.go-mono.com/?link=T%3aMono.Data.Sqlite.SqliteConnection
此代码运行良好,但 2 天后我的程序崩溃了,因为 sqlite.dll 没有正确处理连接。 sqlite.dll 让连接保持打开状态,证据如下:
我的应用程序的进程 ID 是 29140:
然后我 运行 命令 lsof -a -p 29140
然后 returns 我是这样的:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Main 29140 root cwd DIR 8,1 4096 46137345 /root
Main 29140 root rtd DIR 8,1 4096 2 /
Main 29140 root txt REG 8,1 3845024 12586404 /usr/bin/mono-sgen
Main ........
... etc
.... etc
Main 29140 root 74r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 75r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 76r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 77r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 78r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 79r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 80r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 81r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 82r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 83r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 84r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
Main 29140 root 85r REG 8,1 39170048 49023734 /var/log/asterisk/master.db
因为我每秒都查询数据库,所以我希望每秒创建一个 "file lock" 到 /var/log/asterisk/master.db
。这种情况 运行 经常发生!如果数据库被大量使用,我会看到 /var/log/asterisk/master.db
的数量增加。如何正确处理此 sqlite 连接?
我尝试过的事情:
调用 GC.Collect()
和 GC.WaitForPendingFinalizers()
作为这个答案的建议:
我将连接字符串更改为:(Poling=False)
var conString = $"Data Source={dbLocation}; Read Only=True; Pooling=False;";
我也关闭了我的 reader 作为:
// using very important!
using(var command = sqlite3.CreateCommand())
{
command.CommandText = "select * from foo";
var reader = command.ExecuteReader();
// etc...
reader.Close(); // close reader! <----- this is very important for some reason
}
这已经 运行 一小时了,计数没有增加。我希望这是解决方案。