SQLite - 打开一个EXCLUSIVE连接,在失败时回退到SHARED

时间:2015-12-27 10:43:49

标签: c# sqlite connection connection-string

我正试图创造一个“后备”。机制,它将允许进程获得对db文件的EXCLUSIVE锁定,如果失败 - 获得SHARED [= readonly]锁定。

这个想法是,一旦一个进程获得一个EXCLUSIVE锁,它就会在其中一个表中写下一些关于它自己的信息,所以一旦另一个进程试图获得一个EXCLUSIVE锁 - 它将会失败,但是能够执行& #39; SELECT'查询数据库。

我找到了following问题,这个问题只描述了答案的一半 - 我能够获得' EXCLUSIVE'锁定,但我没有找到一种获得“共享”的方法。锁。

伪代码:

try
{
  OpenExclusive();
  // Perform INSERT/UPDATE statements
}
catch(ExclusiveConnectionException)
{
  OpenShared();
  // Perform SELECT statements
}

1 个答案:

答案 0 :(得分:1)

我最终只是通过使用交易来实现它,但首先要确保设置连接字符串' DefaultTimeout'值为' 0':

connection.ConnectionString = "Data Source=...;Version=3;DefaultTimeout=0"

这会阻止'连接。打开'悬挂声明。

connection.Open(); // Opens connection as SHARED
try
{
    // Gain exclusive write-lock by beginning a transaction:
    using (SQLiteCommand cmd = conn.CreateCommand())
    {
        cmd.CommandText = "BEGIN IMMEDIATE";
        cmd.ExecuteNonQuery();
    }
}
catch(SQLiteException ex)
{
    if (ex.ResultCode == SQLiteErrorCode.Busy)
    {
        // Connection is still open as read-only (can perform SELECT statements)
    }
    else
        // Unexpected exception:
        throw;
}

为了使数据保持同步,我们必须在每次写操作后执行COMMIT并重新启动事务:

using (SQLiteCommand cmd = connection.CreateCommand())
{
    // Notice the 'COMMIT; BEGIN IMMEDIATE;' statements in the end:
    cmd.CommandText = "INSERT INTO [SOME_TABLE] VALUES('foo','bar'); COMMIT; BEGIN IMMEDIATE;";
}