База данных заблокирована в режиме WAL только с читателями

Использование System.Data.Sqlite 1.0.86.0 (включая SQLite 3.7.17) вЗапись впереди режим, яя испытываю блокировки базы данных при чтении одновременно, что не должноесли я правильно понимаю WAL. Я'я не пишу и не совершаю ничего, аReadCommitted Режим изоляции транзакции используется правильно, чтобы избежать сериализации чтения.

БД SQLite (с WAL) заблокирована при подготовкеВыбрать" Устав - почему? это похожая проблема. Единственный ответ говорит о звонкеsqlite3_reset после каждогоsqlite3_step, что сделано правильно System.Data.Sqlite, насколько я видел в исходном коде.

Полное воспроизведение:

internal static class Program {

    private const string DbFileName = "test.sqlite";
    private static readonly string _connectionString = BuildConnectionString(DbFileName);

    internal static void Main() {
        File.Delete(DbFileName);
        ExecuteSql("CREATE TABLE Test (Id INT NOT NULL, Name TEXT);", true);
        for (int i = 0; i < 10; i++)
            Task.Run(() => ExecuteSql("SELECT Id, Name FROM Test;", false));
        Console.ReadKey();
    }

    private static string BuildConnectionString(string fileName) {
        var builder = new SQLiteConnectionStringBuilder {
            DataSource = fileName,
            DateTimeFormat = SQLiteDateFormats.ISO8601,
            DefaultIsolationLevel = IsolationLevel.ReadCommitted,
            ForeignKeys = true,
            JournalMode = SQLiteJournalModeEnum.Wal,
            SyncMode = SynchronizationModes.Full
        };
        return builder.ToString();
    }

    private static void ExecuteSql(string sql, bool commit) {
        Stopwatch stopwatch = Stopwatch.StartNew();
        using (var connection = new SQLiteConnection(_connectionString)) {
            connection.Open();
            using (SQLiteTransaction transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted)) {
                using (SQLiteCommand command = connection.CreateCommand()) {
                    command.CommandText = sql;
                    command.ExecuteNonQuery();
                }
                if (commit)
                    transaction.Commit();
            }
        }
        stopwatch.Stop();
        Console.WriteLine("{0}: {1}", stopwatch.Elapsed, sql);
    }

}

Выход:

00:00:00.1927492: CREATE TABLE Test (Id INT NOT NULL, Name TEXT);
00:00:00.0054247: SELECT Id, Name FROM Test;
00:00:00.0055334: SELECT Id, Name FROM Test;
00:00:00.0056022: SELECT Id, Name FROM Test;
00:00:00.0054860: SELECT Id, Name FROM Test;
00:00:00.0053894: SELECT Id, Name FROM Test;
00:00:00.0056843: SELECT Id, Name FROM Test;
00:00:00.0006604: SELECT Id, Name FROM Test;
00:00:00.0006758: SELECT Id, Name FROM Test;
00:00:00.0097950: SELECT Id, Name FROM Test;
00:00:00.0980008: SELECT Id, Name FROM Test;

Вы можете видеть, что последний на порядок медленнее. При выполнении в режиме отладки в окне вывода один или несколько раз регистрируется следующее в зависимости от запуска:

Ошибка SQLite (261): база данных заблокирована

У вас есть идеи, как избежать этой блокировки? Конечно, в этом примере WAL можно просто отключить, но в реальном проекте я могуt: мне нужны потенциальные записи для немедленного успеха, даже если происходит длительная транзакция чтения.

Ответы на вопрос(1)

Ваш ответ на вопрос