为什么 SQLite 不需要调用 commit() 来保存数据?
我在某处读到,要将数据保存到 Python 中的 SQLite 数据库,需要调用 commit()
。但我从来不需要这样做。为什么?
I read somewhere that to save data to an SQLite database in Python, a commit()
call is required. Yet I have never needed to do this. Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这意味着您的 SQLite3 驱动程序处于自动提交模式。
了解提交模式
在事务数据库管理系统中,事务是
根据 ISO/IEC 9075:2011 SQL 标准,如果当前没有活动事务,则事务由启动事务语句显式启动,或者隐式在
事务由提交语句或回滚语句显式终止,或者由事务中止隐式终止(参见 ISO/IEC 9075-2:2011)。
所以几乎所有的SQL语句都是在事务中执行的,事务必须显式提交才能生效。处于此提交模式的数据库接口处于手动提交模式。手动提交模式是一种最佳实践,对于程序(非交互式会话)来说很好,但也可以对于用户来说很麻烦(交互式会话)。因此,大多数数据库接口还为交互式会话提供自动提交模式。自动提交模式下,在除启动事务语句之外的事务启动语句之前隐式发起的事务会在该语句之后隐式提交,而由启动事务语句显式发起的事务必须显式提交才能生效。
数据库接口特定于数据库引擎,因此通常使用更通用的接口与数据库引擎交互(例如开放数据库连接,Java 数据库连接、Python 数据库 API)。通用数据库接口对特定数据库接口的适配是由数据库驱动程序提供的。 SQLite 引擎 在 C 语言中具有特定的数据库接口。 SQLite3 驱动程序 使 Python 数据库 API 适应 SQLite API。
SQL 语句由数据库引擎解释。因此,当数据库引擎和数据库驱动程序处于相同的提交模式(手动提交模式或自动提交模式)时,数据库驱动程序可以将未修改的SQL语句传递给数据库引擎。但是,当它们处于不同的提交模式时,数据库驱动程序必须配置数据库引擎以匹配数据库驱动程序的提交模式,或者在将 SQL 语句传递到数据库引擎之前转换 SQL 语句以模拟数据库驱动的提交模式:
A ; B; 开始交易; D;一个; B;开始交易; C; D;犯罪;开始交易; E; F;回滚;
)。A; B; START TRANSACTION; C; D; COMMIT; E; F;
转换为A; COMMIT; B; COMMIT; START TRANSACTION; C; D;提交;提交;
SQLite 引擎始终处于自动提交模式(参见 SQLite 文档)。 SQLite3 驱动程序默认处于手动提交模式,因此必须模拟它(参见SQLite3 文档)。 SQLite3驱动程序目前并没有像上一段所述那样正确模拟手动提交模式,而是通过在除select语句之外的每个事务启动SQL数据语句之前隐式发出启动事务语句,因此SQL模式语句和select语句不是始终处于显式启动的事务中(参见 SQLite3 实现)。这不符合 Python 数据库 API 规范,因此使用
Connection
类的isolation_level
属性配置的传统手动提交模式和自动提交模式将在 Python 3.12 中被弃用,其中在Connection
类中引入了新的autocommit
属性,用于配置符合 Python 数据库 API 的手动提交模式和自动提交模式(参见 CPython 问题 #83638 和 CPython 拉取请求#93823)。示例 1. - 此 Python 3.11 程序在旧版手动提交模式下使用 SQLite3 驱动程序。
示例 2. — 此 Python 3.12 程序在手动提交模式下使用 SQLite3 驱动程序。
示例 3 - 此 Python 3.11 程序在旧版自动提交模式下使用 SQLite3 驱动程序。
示例 4. — 此 Python 3.12 程序在自动提交模式下使用 SQLite3 驱动程序。
It means that your SQLite3 driver is in auto-commit mode.
Understanding commit modes
In transactional database management systems, a transaction is a sequence of data access operations that is
According to the ISO/IEC 9075:2011 SQL standard, if no transaction is currently active, a transaction is explicitly initiated by a start transaction statement, or implicitly initiated before
And a transaction is explicitly terminated by a commit statement or rollback statement, or implicitly terminated by an abortion of the transaction (cf. ISO/IEC 9075-2:2011).
So almost all SQL statements are executed in a transaction, and the transaction must be explicitly committed to take effect. A database interface that is in this commit mode is in manual commit mode. Manual commit mode is a best practice which is fine for programs (non-interactive sessions) but can be cumbersome for users (interactive sessions). For that reason, most database interfaces also provide an auto-commit mode for interactive sessions. In auto-commit mode, a transaction implicitly initiated before a transaction-initiating statement other than the start transaction statement is implicitly committed after the statement, whereas a transaction explicitly initiated by a start transaction statement must be explicitly committed to take effect.
A database interface is specific to a database engine so more generic interfaces are commonly used to interact with a database engine (e.g. Open Database Connectivity, Java Database Connectivity, Python Database API). The adaptation of a generic database interface to a specific database interface is provided by a database driver. The SQLite engine has a specific database interface in C. The SQLite3 driver adapts the Python Database API to the SQLite API.
SQL statements are interpreted by a database engine. So when a database engine and database driver are in the same commit mode (manual commit mode or auto-commit mode), the database driver can pass unmodified SQL statements to the database engine. However when they are in different commit modes, the database driver has to either configure the database engine to match the commit mode of the database driver, or transform SQL statements before passing them to the database engine to emulate the commit mode of the database driver:
A; B; START TRANSACTION; C; D; COMMIT; E; F;
is transformed intoSTART TRANSACTION; A; B; START TRANSACTION; C; D; COMMIT; START TRANSACTION; E; F; ROLLBACK;
).A; B; START TRANSACTION; C; D; COMMIT; E; F;
is transformed intoA; COMMIT; B; COMMIT; START TRANSACTION; C; D; COMMIT; E; COMMIT; F; COMMIT;
).The SQLite engine is always in auto-commit mode (cf. the SQLite documentation). The SQLite3 driver is by default in manual commit mode so has to emulate it (cf. the SQLite3 documentation). The SQLite3 driver currently does not emulate manual commit mode properly like described in the previous paragraph, but by implicitly issuing a start transaction statement before each transaction-initiating SQL-data statements other than select statements, so SQL-schema statements and select statements are not always in an explicitly initiated transaction (cf. the SQLite3 implementation). That is not Python Database API-conformant so the legacy manual commit mode and auto-commit mode configured with the
isolation_level
attribute of theConnection
class will be deprecated in Python 3.12 with the introduction of a newautocommit
attribute in theConnection
class for configuring the Python Database API-conformant manual commit mode and auto-commit mode (cf. CPython issue #83638 and CPython pull request #93823).Example 1. — This Python 3.11 program uses the SQLite3 driver in legacy manual commit mode.
Example 2. — This Python 3.12 program uses the SQLite3 driver in manual commit mode.
Example 3. — This Python 3.11 program uses the SQLite3 driver in legacy auto-commit mode.
Example 4. — This Python 3.12 program uses the SQLite3 driver in auto-commit mode.
可能自动提交已打开,默认情况下 http://www.sqlite.org/c3ref/get_autocommit。 html
Probably autocommit is on, it is by default http://www.sqlite.org/c3ref/get_autocommit.html
添加
isolation_level=None
进行连接(Ref )Add
isolation_level=None
to connect (Ref)连接对象还可以用作自动提交或回滚事务的上下文管理器。 11.13.7.3。在 docs.python
also connection objects can be used as context managers that automatically commit or rollback transactions. 11.13.7.3. on docs.python
Python sqlite3 在“INSERT”或“UPDATE”之前自动发出 BEGIN 语句。之后它会自动提交任何其他命令或 db.close()
Python sqlite3 issues a BEGIN statement automatically before "INSERT" or "UPDATE". After that it automatically commits on any other command or db.close()