9

正如我可以从SQLite FAQ中看到的,它在任何时候都支持多个进程读取(SELECT)和一个进程写入(INSERT、UPDATE、DELETE)数据库:

SQLite 使用读/写锁来控制对数据库的访问。当任何进程想要写入时,它必须在其更新期间锁定整个数据库文件。但这通常只需要几毫秒。其他流程只是等待作者完成然后继续他们的业务

我正在通过 c#使用System.Data.SQLite适配器。

有人可以向我解释一下,这个过程到底是怎么回事?

如果已经在同一个数据库上执行另一个写入SQLiteCommand,这个过程是否会自动工作并且写入SQLiteCommand将只是等待?

或者它可能会抛出异常?什么样的?

抱歉,我没有找到有关此机制的信息 :)

谢谢你。

更新:

我发现帖子说使用特定的错误代码引发异常

这种说法正确吗?

4

1 回答 1

17

我自己调查过:

我创建了一个示例 SQLite 数据库c:\123.db,其中一个表Categories包含两个字段:ID(uniqueidentifier) 和Name(nvarchar)。

System.Data.SQLite然后我编写了一些多线程代码来模拟对数据库的多次写入访问(如果您使用此代码,请不要忘记添加对您的项目的引用):

using System;
using System.Data.SQLite;
using System.Threading.Tasks;

namespace SQLiteTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var tasks = new Task[100];

            for (int i = 0; i < 100; i++)
            {
                tasks[i] = new Task(new Program().WriteToDB);
                tasks[i].Start();
            }

            foreach (var task in tasks)
                task.Wait();
        }

        public void WriteToDB()
        {
            try
            {
                using (SQLiteConnection myconnection = new SQLiteConnection(@"Data Source=c:\123.db"))
                {
                    myconnection.Open();
                    using (SQLiteTransaction mytransaction = myconnection.BeginTransaction())
                    {
                        using (SQLiteCommand mycommand = new SQLiteCommand(myconnection))
                        {
                            Guid id = Guid.NewGuid();

                            mycommand.CommandText = "INSERT INTO Categories(ID, Name) VALUES ('" + id.ToString() + "', '111')";
                            mycommand.ExecuteNonQuery();

                            mycommand.CommandText = "UPDATE Categories SET Name='222' WHERE ID='" + id.ToString() + "'";
                            mycommand.ExecuteNonQuery();

                            mycommand.CommandText = "DELETE FROM Categories WHERE ID='" + id.ToString() + "'";
                            mycommand.ExecuteNonQuery();
                        }
                        mytransaction.Commit();
                    }
                }
            }
            catch (SQLiteException ex)
            {
                if (ex.ReturnCode == SQLiteErrorCode.Busy)
                    Console.WriteLine("Database is locked by another process!");
            }
        }
    }
}

我的 Core2Duo E7500 上的结果是从未引发异常!

看起来 SQLite 已经针对我的需要进行了足够的优化(锁定/解锁非常快,通常只需要几毫秒,正如SQLite 常见问题解答告诉我们的那样) - 太棒了!

请注意,不需要为 an 检索整数 ErrorCode SQLiteException- 您可以改用特殊的枚举ReturnCode字段。此处描述了所有代码。

希望这些信息对某人有所帮助。

于 2013-03-14T06:33:26.293 回答