C# 通过System.Data.SQLite和c对单个SQLite数据库文件进行多重访问
如我所知,它支持多个进程读取、选择和仅一个进程写入随时插入、更新、删除数据库: SQLite使用读写器锁来控制对数据库的访问。 当任何进程想要写入时,它必须锁定整个数据库文件 在其更新期间。但这通常只需要几分钟 毫秒。其他进程只需等待编写器完成即可 继续他们的生意 我通过c使用适配器 有人能告诉我这个过程到底是怎么进行的吗 如果在同一数据库上已经有另一个正在写入SQLiteCommand的命令正在执行,那么这个过程是否会自动工作,写入SQLiteCommand将只是等待 或者它会抛出一个异常?什么样的 抱歉,我找不到有关此机制的信息: 多谢各位 更新: 我发现有一个帖子说,有一个特定的错误代码C# 通过System.Data.SQLite和c对单个SQLite数据库文件进行多重访问,c#,database,sqlite,locking,system.data.sqlite,C#,Database,Sqlite,Locking,System.data.sqlite,如我所知,它支持多个进程读取、选择和仅一个进程写入随时插入、更新、删除数据库: SQLite使用读写器锁来控制对数据库的访问。 当任何进程想要写入时,它必须锁定整个数据库文件 在其更新期间。但这通常只需要几分钟 毫秒。其他进程只需等待编写器完成即可 继续他们的生意 我通过c使用适配器 有人能告诉我这个过程到底是怎么进行的吗 如果在同一数据库上已经有另一个正在写入SQLiteCommand的命令正在执行,那么这个过程是否会自动工作,写入SQLiteCommand将只是等待 或者它会抛出一个异常?什
那句话对吗 我自己调查过: 我创建了一个示例SQLite数据库c:\123.db,其中一个表类别包含两个字段: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已经针对我的需要进行了充分的优化,锁定/解锁速度非常快,通常只需要几毫秒,这告诉我们-太棒了
请注意,无需检索SQLiteException的整数ErrorCode-您可以改用特殊的enum ReturnCode字段。描述了所有代码
希望这些信息能对某人有所帮助。还没有:我更喜欢在编码之前阅读教程-以获得优化和正确的解决方案…如果您更喜欢优化和正确的解决方案,请不要将SQLite用于它未优化的内容;这是一个伟大的数据库,但它不是一个伟大的多用户数据库。我需要免费和轻量级的,我的意思是零配置和无服务器数据库为我的项目。因此,大多数多用户优化的数据库不适合我:您的代码证明,单个进程中的多个线程可以无缝地访问SQLite数据库。您是否能够测试多个不同的进程是否可以访问同一个数据库?首先,我想到的是在Test1.exe中编译该代码,然后在Main的第一行添加Process.StartTest1.exe并将其重新编译到Test2.exe。似乎是工作,但我从来没有测试过它…好主意!我刚刚使用这种方法进行了测试,它是有效的。多进程访问在SQLite上运行得很好。只是想补充一下。我正在编写一个基于NLog/SignalR的保证交付日志服务,该服务使用System.Data.SQLite写入本地数据库,以便后台线程将数据发送到LogStash,我有40个线程将日志消息发送到本地SignalR hub。它肯定是抛出了SQLite错误5:当单个进程处理来自其他进程的其他线程的消息时,数据库被锁定异常。@JamesEby SQLite使用内部日志记录,因此当某个操作由于块状态或其他原因而失败时,它会重试直到完成。所以,这不是内部条件,当然,您的插入没有丢失。事实上,如果您看到该消息,则会发生错误,稍后会重试。使用线程插入时,这种锁定错误很常见。除此之外,如果您有大量的线程读取,则使用WAL日志模型,因此写入和读取在单独的线程中,因此来自线程的写入不会影响可能的数千次并发读取。