我有一个web应用程序使用sqlite数据库。 我的版本的sqlite是官方windows二进制发行版的最新版本 - 3.7.13。sqlite在WAL模式下返回SQLITE_BUSY
问题是,在数据库的重负载下,sqlite API函数(如sqlite3_step)正在返回SQLITE_BUSY。
我初始化连接时,通过以下编译:
journal_mode = WAL
page_size = 4096
synchronous = FULL
foreign_keys = on
的databas是一个文件数据库。我使用Mono 2.10.8和Mono.Data.Sqlite程序集来访问数据库。
我用50个并行线程测试它,每个线程发送50个后续http请求到我的应用程序。在每次请求时,都会对数据库进行一些读写操作。每一组IO操作都在事务内执行。
一切顺利,直到接近第400 - 700的要求。在这个(随机)时刻,API函数开始永久返回SQLITE_BUSY(更确切地说 - 直到达到重试限制)。
就我所知,WAL模式透明地支持并行读写。我猜测这可能是因为尝试在检查点操作执行时读取数据库。但即使在关闭自动检测点之后,情况仍然如此。
在这种情况下会出现什么问题? 如何正确提供大量的并行数据库IO?
P.S.
假设每个请求只有一个连接。 我使用配置了WebSessionContext的nhibernate。
我初始化我NHibernate的会议上是这样的:
ISession session = null;
//factory variable is session factory
if (CurrentSessionContext.HasBind(factory))
{
session = factory.GetCurrentSession();
if (session == null)
CurrentSessionContext.Unbind(factory);
}
if (session == null)
{
session = factory.OpenSession();
CurrentSessionContext.Bind(session);
}
return session;
而且在HttpApplication.EndRequest我释放这样的:
//factory variable is session factory
if (CurrentSessionContext.HasBind(factory))
{
try
{
CurrentSessionContext.Unbind(factory)
.Dispose();
}
catch (Exception ee)
{
Logr.Error("Error uninitializing session", ee);
}
}
所以据我了解应该是每个只有一个连接请求生命周期。在处理请求时,代码将按顺序执行(ASP.NET MVC 3)。所以在这里看起来并不是什么可能。我可以得出结论,在这种情况下没有连接共享吗?
为每个请求打开了一个独特的连接,还是所有请求都共享相同的连接?另外,你可以添加一些相关的代码,尤其是线程与数据库交互的部分吗? – 2012-08-29 10:37:57
你对WAL模式的假设是错误的。 http://www.sqlite.org/wal.html说:“因为只有一个WAL文件,所以一次只能有一个作者。”对于有大量写入负载的数据库,请使用PostgreSQL或MySQL之类的东西。 – 2012-09-02 12:50:10