带有并发数据库更新的Sqlite3死锁,VB .net

时间:2013-09-05 10:42:57

标签: vb.net sqlite concurrency deadlock

我的程序由许多类组成,这些类运行自己的更新函数来检查sqlite数据库,并在发现更改时进行更新。

Async Function update() As Task(Of String)
.
.
  Await Task.Run(Sub()
    .
    .                          
  End Sub)
.
.
  helper.updatedb(par1, par2, par3, par4)
.
.
End Function

Sub updatedb(ByVal name As String, ByVal entry As String, ByVal smth As String, Optional ByVal random As String = vbNullString)

            Dim SQLconnect As New SQLite.SQLiteConnection()
            Dim SQLcommand As SQLiteCommand
            SQLconnect.ConnectionString = "data source=" + dbpath
            SQLconnect.Open()
            SQLcommand = SQLconnect.CreateCommand
            SQLcommand.CommandText = "SELECT ""entry"" FROM profiles WHERE ""name"" = @name"
            SQLcommand.Parameters.AddWithValue("@name", LCase(name))
            Dim SQLreader As SQLiteDataReader = SQLcommand.ExecuteReader()
            SQLreader.Read()

            Dim result As String = SQLreader(0)

                SQLcommand.Dispose()
                SQLcommand = SQLconnect.CreateCommand
                SQLcommand.CommandText = "UPDATE profiles SET ""entry"" = @entry WHERE ""name"" = @name"
                SQLcommand.Parameters.AddWithValue("@name", LCase(name))
                SQLcommand.Parameters.AddWithValue("@entry", entry)

                SQLcommand.ExecuteNonQuery()

            SQLcommand.Dispose()
            SQLreader.Close()
            SQLconnect.Close()
            SQLconnect.Dispose()
    End Sub

执行SQLcommand.ExecuteNonQuery时可能会出现问题,而另一个线程可能具有对db的写入权限。 “在System.Data.SQLite.dll中发生'System.Data.SQLite.SQLiteException'类型的第一次机会异常”。

我在其他一些帖子中读到,可以使用更新命令上的互斥锁来解决这个问题。我如何将mutex实现到我的代码中?是否有一些sqlite替代方案有利于可移植性并且没有这样的并发问题?

2 个答案:

答案 0 :(得分:0)

请参阅this online help

您创建锁定变量,然后将其锁定;只有一个线程可以一次锁定,其他线程自动等待:

Dim lockThis As New Object

Sub updatedb(ByVal name As String, ...)
    SyncLock lockThis
        Dim SQLconnect As New SQLite.SQLiteConnection()
        ...
    End SyncLock
End Sub

答案 1 :(得分:0)

好吧,我会被诅咒......似乎问题在于放置处置陈述:

Dim SQLreader As SQLiteDataReader = SQLcommand.ExecuteReader()
->SQLcommand.Dispose()
SQLreader.Read()

Dim result As String = SQLreader(0)
->SQLreader.Close()

现在它按预期工作......