在生产环境中使用SQLite与Django?

34

很抱歉有这样一个问题,我不确定我是否理解了这个概念,但SQLite是无服务器的,这意味着数据库在本地计算机中,并且存储在一个文件中,这个文件只能在一个模式下访问:如果一个客户端读取它,它就为其他客户端制作了只读模式,如果一个客户端写入,则所有客户端都具有写入模式,因此一次只能处于一种模式! 那么想象一下,我做了一个Django应用程序,例如一个博客;那么如何使用SQLite进行处理?既然如果客户端进入博客,他会获得阅读模式以查看页面和博客条目,如果注册客户尝试添加评论,则文件将被设置为写模式,那么SQLite如何处理这个问题? 所以,SQLite只是像Django附带的BaseHTTPServer(服务器)一样,只是为了测试和学习目的而存在吗?

7个回答

47
不同的数据库采用不同的并发管理方式,而在sqlite中,使用的方法是全局数据库级锁。一次只有一个线程或进程可以更改sqlite数据库;所有其他并发进程将被迫等待当前正在运行的进程完成。随着用户数量的增加,sqlite简单的锁定策略将导致越来越大的锁争用,您需要将数据迁移到另一个数据库,如MySQL(至少可以使用InnoDB引擎进行行级锁定)或PostgreSQL(它使用多版本并发控制)。如果您预计将拥有大量用户(例如,在一天的很大一部分时间内每秒超过1个请求),则应该将数据从sqlite迁移出去;而且越早这样做,就越容易。

1
我使用PostgreSQL和MySQL。对于大型项目,我更喜欢使用PostgreSQL,主要是因为它支持事务处理,但对于较小的应用程序,MySQL也可以胜任。 - Rob Osborne

15

SQLite并不像BaseHTTPServer或其他基础的东西。它是一个功能齐全的嵌入式数据库,而且速度相当快。虽然它的SQL语言可能没有最多的花哨功能,但它足够灵活。在我参与的项目中(这些项目并不是您典型的Web应用程序),我还没有遇到过需要它无法完成的情况。

任何声称SQLite适合或不适合生产环境的人,如果没有讨论实际设计,那么他们并没有告诉你太多。SQLite非常快。在某些情况下,它比Djangonauts经常使用的替代方案Postgres要快得多,甚至可以说是数量级的差距。正如有人指出的那样,它也支持大量并发。问题在于你的应用程序是否属于“某些情况”。

现在,有一个重要的因素必须考虑进去。SQLite是一个进程内数据库。这一点非常重要。如果你正在使用类似gevent之类的东西,你可能会遇到一些边缘情况,导致你的应用程序崩溃。例如,在事务中间进行上下文切换可能会以可怕的方式破坏事务。换句话说,“并发”取决于你的应用程序,因为SQLite是你的应用程序的一部分。

然而,就扩展性而言,使用SQLite做不到像其他数据库引擎一样构建服务器集群,因为它是进程内的。尽管如此,你的应用程序可能或可能不需要在扩展方面采取如此之长的路程,但我猜测大部分应用程序都不需要(野蛮猜测)。

另一方面,作为进程内部,将自定义函数和聚合添加到其中非常简单。我不确定Django的ORM是否比必须要更加困难,但是你可以利用这些功能提出相当好的设计。


1
并发性的说法很混乱。是的,有一定程度的并发性,但它指的是多个嵌入式应用程序的并发性。这不是我们在这里讨论的内容。Django每个页面请求使用一个全局锁,这意味着一旦页面上有多个同时点击,它很快就会被锁竞争所阻塞。开发人员强烈建议不要在生产中使用它,这是有充分理由的。 - Shayne

12

在数据库理论中,这个问题被称为并发,根据常见问题解答(FAQ)页面,SQLite支持Windows 98及以上版本中的并发处理功能:

http://www.sqlite.org/faq.html#q5

我们不知道还有哪些嵌入式SQL数据库引擎支持像SQLite这样多的并发处理。 SQLite允许多个进程同时打开数据库文件,并且允许多个进程同时读取数据库文件。当任何一个进程想要进行写操作时,它必须锁定整个数据库文件以完成其更新,但这通常只需几毫秒的时间。其他进程只需等待写入者完成后再继续进行。而其他嵌入式SQL数据库引擎通常只允许单个进程连接到数据库。

基本上,不用担心并发问题,任何值得使用的数据库都可以很好地处理它。更多关于SQLite3如何管理该问题的信息可以在此处找到。作为开发人员而不是数据库设计师,您不需要关注它,除非您对其内部工作感兴趣。


所以这只是一个几秒钟的问题?就像时间共享的想法吗? - Abdelouahab
那些全局锁在热门网站上很快就会堆积起来。相信我。此外,并发性并不是重点。这是与嵌入式数据库进行比较。这种并发性甚至不在像Postgres、MySQL、MSSQL或Oracle这样的RDBMS中找到的并发性范围内,那里可能有数千个客户端。我们曾经在一份政府工作中使用Postgres服务器每天从数千个客户端摄取数千兆字节的GIS数据。你不可能在Sqlite数据库上做到这一点。 - Shayne

8

SQLite只有在特定情况下才能有效地用于生产。即使在Windows上,也很容易启动MySQL或PostgreSQL,并拥有大多数情况下可用的数据库。

真正的问题在于Django中的SQLite3不是线程化的,因此您的服务器上一次只能发生一个页面视图,请参见此错误https://code.djangoproject.com/ticket/12118 已修复

我甚至在开发中都不使用SQLite3。

编辑:我一直在这里遭受负评,但Django文档本身建议不要在生产中使用SQLite3,当时我写这篇回答。文档仍然包含以下警告:

SQLite为那些主要是只读或需要较小安装占用空间的应用程序提供了一个很好的开发替代方案。

如果您没有小型占用空间/只读的Django实例,则不要使用SQLite3。请继续对此答案进行负投票。


4
SQLite也适合用来教授数据库概念(因为它易于设置),以及研究(因为其源代码简单、规模小)。对于这些方面,SQLite表现得非常出色。但如果需要处理大量交易负载,则有更好的选择。 - SingleNegationElimination
2
是的,测试/开发阶段。一旦您开始构建更复杂的网站,您将需要一个真正的数据库,并且您可能需要一些原始的SQL(我已经构建了3个Django网站,所有这三个都需要一些原始SQL来进行一些查询)。 - Rob Osborne
3
“SQLite 不适合生产环境”这种说法是错误的,请参考 SQLite 文档。 - Marcin
1
根据SQLite的说法,对于每天处理400k次点击、包含一些动态内容和每次点击200个查询的网站来说,SQLite是一个不错的选择。因此,我认为说SQLite不适用于Django大多是无稽之谈,除非你需要处理大量流量。如果你正在考虑这个问题,那么SQLite可能是可以的,而且相对于基于服务器的数据库,它可能更容易使用和备份。总的来说,我更相信SQLite文档,因为他们的大部分声明都有真实世界的测试支持。Django是否提供支持该声明的数字呢?https://www.sqlite.org/whentouse.html - Josh
1
@RobOsborne 这很公正,尽管它仍然相关,人们仍然经常问这个问题。我们可以同意不同意sqlite不适用于生产环境 - 对我来说,Django的文档表明,除非您期望有大量流量,否则它是可以使用的。我建议还要删除线程错误,因为它在一段时间前已在跟踪器中修复:https://code.djangoproject.com/ticket/12118 - Josh
显示剩余3条评论

4
在生产中使用Django与Sqlite作为数据库并不是不可能的,这主要取决于您的网站/网络应用程序流量以及对数据库的查询操作的频率和复杂程度(包括读/写等)。事实上,接近2019年底,我已经在几个低流量应用程序中使用它,每天不到5k次交互(这比你想象的更常见)。
简而言之,在当前技术状态下,目前的Sqlite-3支持无限并发读取(或者说取决于您的机器/工作人员能处理多少),但是只有一个进程可以在任何时间点上写入它。请记住,对数据库进行良好设计的查询/操作只需要毫秒级的时间!
从使用Sqlite作为唯一数据库的经验来看,对于处理约5000名注册学生的海外求职匹配简单非例行性(我指的是典型用户不会全年每天都使用此应用程序)生产Web应用程序(统计数据显示,峰值期间涉及命中数据库的请求不到2k次,其中40%为写入操作,60%为读取操作),我从未遇到过超时/性能问题。
真正的关键在于对开发和客户规格说明书(URS)实际的看法。如果它成为下一个独角兽,您随时可以将Sqlite迁移到另一个关系型数据库管理系统(RDBMS)。例如,请参见David d C e Freitas在Quick easy way to migrate SQLite3 to MySQL?中关于迁移的看法。
此外,Sqlite网站使用Sqlite数据库作为其后端...请参见下面...
引文:“SQLite”网站(https://www.sqlite.org/)自然会使用SQLite本身,并且截至本文撰写日期(2015年),它每天处理约400K到500K个HTTP请求,其中约15-20%是涉及数据库的动态页面。每个网页的动态内容使用约200个SQL语句。这个设置运行在一台单独的虚拟机上,与其他23台服务器共享一台物理服务器,并且大部分时间负载平均值低于0.1。
请记住,上述引用主要是指读取操作,因此这些值可能不适用于写入量较大的站点。
我以上所提到的使用Sqlite作为数据库构建的求职匹配应用程序相当重视写入操作,如果您注意到了这些数字...平均而言,40%是短暂的写入操作(例如表单提交等),但是请记住,在高峰期每天只有2k次访问量。

如果你发现你的sqlite.db导致了很多超时和糟糕的用户体验(例如提交表单时出现408错误...),特别是当Django抛出“OperationalError: database is locked error.”(然后他们不得不重新输入所有内容)时... 你可以根据django文档在settings.py中暂时增加超时时间作为临时解决方案,同时准备迁移数据库。

'OPTIONS': {
# ...
'timeout': 20,
# ...
}

最终,一切都取决于务实的开发和面对现实,即网站可能无法吸引如预期的那样多的活动,并且很容易在开始时过度设计。

有很多时候,采用简单的解决方案可以更快地进入市场,基本上是快速测试水域,并且当然要做好准备,如果食肉鱼群涌来,那就是升级到另一个关系型数据库的时候了。

使用 Django 的 ORM,在大多数情况下,您不需要在迁移到其他支持的 SQL 数据库时修改 models.py。请注意, Sqlite 不支持一些更高级的函数或甚至是 MYSQL 和 POSTGRES 这些更大的“表亲”所支持的某些字段。


1
迟到了,但这个问题在2018年中仍然很重要。
博客网站的“客户端”是一个不同于“数据库客户端”的术语。SQLite文档将客户端称为打开数据库文件的进程。例如,一个django应用程序可能同时处理许多Web应用程序客户端(“用户”),但从SQLiite的角度来看,仍然只有一个客户端。
选择SQLite而不是适当的RDBMS的重要考虑因素是您的架构是否由多个软件组件连接到数据库。在这种情况下,使用SQLite可能会成为主要性能瓶颈,因为每个应用程序都需要访问相同的DB文件,可能需要通过网络进行访问。
如果不涉及多个应用程序(数据库客户端),则SQLite在99%的情况下都是一个很好的生产选择。剩下的1%是使用特定DB功能的应用程序,承受巨大负载的应用程序等。
了解您的架构。

1

这个问题的答案取决于您想要在生产中部署的应用程序:

根据SQLite网站上的使用方法,SQLite作为大多数低到中等流量网站的数据库引擎,在生产中表现良好。

他们认为,SQLite可以处理的Web流量量取决于您的网站数据库使用情况。已知任何每天少于100K次点击的网站都可以很好地使用SQLite。但是,这个100K次点击/天的数字是一个保守估计,而不是硬性上限。

总之,SQLite可能是用户和数据库使用较少的应用程序的绝佳选择。因此,对于与数据库交互较少或中等的网站,请使用SQLite,对于与数据库交互较多的网站,请使用MySQL或PostgreSQL。

参考:sqlite.org


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接