{"title":"数据库事务","version":"2.1","locale":"zh-hans","docname":"topics/db/transactions","url":"/zh-hans/2.1/topics/db/transactions/","canonical":"https://djangodocs.dev/zh-hans/2.1/topics/db/transactions/","summary":"Django 提供多种方式控制数据库事务。 管理数据库事务 Link to this heading # Django 默认的事务行为 Link to this heading # Django 默认的事务行为是自动提交。除非事务正在执行，每个查询将会马上自动提交到数据库。 详见 . Django…","html":"<span id=\"database-transactions\"></span><h1>数据库事务<a class=\"heading-anchor\" href=\"#module-django.db.transaction\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django 提供多种方式控制数据库事务。</p>\n<section id=\"managing-database-transactions\">\n<h2>管理数据库事务<a class=\"heading-anchor\" href=\"#managing-database-transactions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"django-s-default-transaction-behavior\">\n<h3>Django 默认的事务行为<a class=\"heading-anchor\" href=\"#django-s-default-transaction-behavior\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 默认的事务行为是自动提交。除非事务正在执行，每个查询将会马上自动提交到数据库。 <a class=\"reference internal\" href=\"#autocommit-details\"><span class=\"std std-ref\">详见</span></a>.</p>\n<p>Django 自动使用事务或还原点，以确保需多次查询的 ORM 操作的一致性，特别是 <a class=\"reference internal\" href=\"/zh-hans/2.1/topics/db/queries/#topics-db-queries-delete\"><span class=\"std std-ref\">delete()</span></a> 和 <a class=\"reference internal\" href=\"/zh-hans/2.1/topics/db/queries/#topics-db-queries-update\"><span class=\"std std-ref\">update()</span></a> 操作.</p>\n<p>由于性能原因，Django 的 <a class=\"reference internal\" href=\"/zh-hans/2.1/topics/testing/tools/#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TestCase</span></code></a> 类同样将每个测试用事务封装起来。</p>\n</section>\n<section id=\"tying-transactions-to-http-requests\">\n<span id=\"id1\"></span><h3>连结事务与 HTTP 请求<a class=\"heading-anchor\" href=\"#tying-transactions-to-http-requests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>在 Web 里，处理事务比较常用的方式是将每个请求封装在一个事务中。 在你想启用该行为的数据库中，把配置中的参数 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ATOMIC_REQUESTS</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>。</p>\n<p>它是这样工作的：在调用试图方法前，Django 先生成一个事务。如果响应能正常生成，Django 会提交该事务。而如果视图出现异常，Django 则会回滚该事务。</p>\n<p>你可以在你的视图代码中使用还原点执行子事务，一般会使用 :func:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>atomic 上下文管理器。但是，在视图结束时，要么所有的更改都被提交，要么所有的更改都不被提交。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>While the simplicity of this transaction model is appealing, it also makes it\ninefficient when traffic increases. Opening a transaction for every view has\nsome overhead. The impact on performance depends on the query patterns of your\napplication and on how well your database handles locking.</p>\n</aside>\n<aside class=\"admonition-per-request-transactions-and-streaming-responses admonition\">\n<p class=\"admonition-title\">Per-request transactions and streaming responses</p>\n<p>When a view returns a <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/request-response/#django.http.StreamingHttpResponse\" title=\"django.http.StreamingHttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">StreamingHttpResponse</span></code></a>, reading\nthe contents of the response will often execute code to generate the\ncontent. Since the view has already returned, such code runs outside of\nthe transaction.</p>\n<p>Generally speaking, it isn't advisable to write to the database while\ngenerating a streaming response, since there's no sensible way to handle\nerrors after starting to send the response.</p>\n</aside>\n<p>In practice, this feature simply wraps every view function in the <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>\ndecorator described below.</p>\n<p>Note that only the execution of your view is enclosed in the transactions.\nMiddleware runs outside of the transaction, and so does the rendering of\ntemplate responses.</p>\n<p>When <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ATOMIC_REQUESTS</span></code></a> is enabled, it's\nstill possible to prevent views from running in a transaction.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.non_atomic_requests\">\n<span class=\"sig-name descname\"><span class=\"pre\">non_atomic_requests</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.non_atomic_requests\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>This decorator will negate the effect of <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ATOMIC_REQUESTS</span></code></a> for a given view:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">transaction</span>\n\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">non_atomic_requests</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">do_stuff</span><span class=\"p\">()</span>\n\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">non_atomic_requests</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;other&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_other_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">do_stuff_on_the_other_database</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>It only works if it's applied to the view itself.</p>\n</dd></dl>\n\n</section>\n<section id=\"controlling-transactions-explicitly\">\n<h3>Controlling transactions explicitly<a class=\"heading-anchor\" href=\"#controlling-transactions-explicitly\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django provides a single API to control database transactions.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.atomic\">\n<span class=\"sig-name descname\"><span class=\"pre\">atomic</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">savepoint</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.atomic\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Atomicity is the defining property of database transactions. <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code>\nallows us to create a block of code within which the atomicity on the\ndatabase is guaranteed. If the block of code is successfully completed, the\nchanges are committed to the database. If there is an exception, the\nchanges are rolled back.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> blocks can be nested. In this case, when an inner block\ncompletes successfully, its effects can still be rolled back if an\nexception is raised in the outer block at a later point.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> is usable both as a <a class=\"reference external\" href=\"https://docs.python.org/3/glossary.html#term-decorator\" title=\"(in Python v3.14)\"><span class=\"xref std std-term\">decorator</span></a>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">transaction</span>\n\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">viewfunc</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"c1\"># This code executes inside a transaction.</span>\n    <span class=\"n\">do_stuff</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>and as a <a class=\"reference external\" href=\"https://docs.python.org/3/glossary.html#term-context-manager\" title=\"(in Python v3.14)\"><span class=\"xref std std-term\">context manager</span></a>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">transaction</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">viewfunc</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"c1\"># This code executes in autocommit mode (Django&#39;s default).</span>\n    <span class=\"n\">do_stuff</span><span class=\"p\">()</span>\n\n    <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>\n        <span class=\"c1\"># This code executes inside a transaction.</span>\n        <span class=\"n\">do_more_stuff</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Wrapping <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> in a try/except block allows for natural handling of\nintegrity errors:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">IntegrityError</span><span class=\"p\">,</span> <span class=\"n\">transaction</span>\n\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">viewfunc</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">create_parent</span><span class=\"p\">()</span>\n\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>\n            <span class=\"n\">generate_relationships</span><span class=\"p\">()</span>\n    <span class=\"k\">except</span> <span class=\"n\">IntegrityError</span><span class=\"p\">:</span>\n        <span class=\"n\">handle_exception</span><span class=\"p\">()</span>\n\n    <span class=\"n\">add_children</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>In this example, even if <code class=\"docutils literal notranslate\"><span class=\"pre\">generate_relationships()</span></code> causes a database\nerror by breaking an integrity constraint, you can execute queries in\n<code class=\"docutils literal notranslate\"><span class=\"pre\">add_children()</span></code>, and the changes from <code class=\"docutils literal notranslate\"><span class=\"pre\">create_parent()</span></code> are still\nthere. Note that any operations attempted in <code class=\"docutils literal notranslate\"><span class=\"pre\">generate_relationships()</span></code>\nwill already have been rolled back safely when <code class=\"docutils literal notranslate\"><span class=\"pre\">handle_exception()</span></code> is\ncalled, so the exception handler can also operate on the database if\nnecessary.</p>\n<aside class=\"admonition-avoid-catching-exceptions-inside-atomic admonition\">\n<p class=\"admonition-title\">Avoid catching exceptions inside <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code>!</p>\n<p>When exiting an <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> block, Django looks at whether it's exited\nnormally or with an exception to determine whether to commit or roll\nback. If you catch and handle exceptions inside an <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> block,\nyou may hide from Django the fact that a problem has happened. This\ncan result in unexpected behavior.</p>\n<p>This is mostly a concern for <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/exceptions/#django.db.DatabaseError\" title=\"django.db.DatabaseError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">DatabaseError</span></code></a> and its\nsubclasses such as <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/exceptions/#django.db.IntegrityError\" title=\"django.db.IntegrityError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">IntegrityError</span></code></a>. After such an\nerror, the transaction is broken and Django will perform a rollback at\nthe end of the <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> block. If you attempt to run database\nqueries before the rollback happens, Django will raise a\n<a class=\"reference internal\" href=\"/zh-hans/2.1/ref/exceptions/#django.db.transaction.TransactionManagementError\" title=\"django.db.transaction.TransactionManagementError\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionManagementError</span></code></a>. You may\nalso encounter this behavior when an ORM-related signal handler raises\nan exception.</p>\n<p>The correct way to catch database errors is around an <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> block\nas shown above. If necessary, add an extra <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> block for this\npurpose. This pattern has another advantage: it delimits explicitly\nwhich operations will be rolled back if an exception occurs.</p>\n<p>If you catch exceptions raised by raw SQL queries, Django's behavior\nis unspecified and database-dependent.</p>\n</aside>\n<aside class=\"admonition-you-may-need-to-manually-revert-model-state-when-rolling-back-a-transaction admonition\">\n<p class=\"admonition-title\">You may need to manually revert model state when rolling back a transaction.</p>\n<p>The values of a model's fields won't be reverted when a transaction\nrollback happens. This could lead to an inconsistent model state unless\nyou manually restore the original field values.</p>\n<p>For example, given <code class=\"docutils literal notranslate\"><span class=\"pre\">MyModel</span></code> with an <code class=\"docutils literal notranslate\"><span class=\"pre\">active</span></code> field, this snippet\nensures that the <code class=\"docutils literal notranslate\"><span class=\"pre\">if</span> <span class=\"pre\">obj.active</span></code> check at the end uses the correct\nvalue if updating <code class=\"docutils literal notranslate\"><span class=\"pre\">active</span></code> to <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> fails in the transaction:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">DatabaseError</span><span class=\"p\">,</span> <span class=\"n\">transaction</span>\n\n<span class=\"n\">obj</span> <span class=\"o\">=</span> <span class=\"n\">MyModel</span><span class=\"p\">(</span><span class=\"n\">active</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n<span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">active</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>\n        <span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n<span class=\"k\">except</span> <span class=\"n\">DatabaseError</span><span class=\"p\">:</span>\n    <span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">active</span> <span class=\"o\">=</span> <span class=\"kc\">False</span>\n\n<span class=\"k\">if</span> <span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">active</span><span class=\"p\">:</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n</aside>\n<p>In order to guarantee atomicity, <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> disables some APIs. Attempting\nto commit, roll back, or change the autocommit state of the database\nconnection within an <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> block will raise an exception.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> takes a <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> argument which should be the name of a\ndatabase. If this argument isn't provided, Django uses the <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;default&quot;</span></code>\ndatabase.</p>\n<p>Under the hood, Django's transaction management code:</p>\n<ul class=\"simple\">\n<li><p>opens a transaction when entering the outermost <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> block;</p></li>\n<li><p>creates a savepoint when entering an inner <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> block;</p></li>\n<li><p>releases or rolls back to the savepoint when exiting an inner block;</p></li>\n<li><p>commits or rolls back the transaction when exiting the outermost block.</p></li>\n</ul>\n<p>You can disable the creation of savepoints for inner blocks by setting the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">savepoint</span></code> argument to <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>. If an exception occurs, Django will\nperform the rollback when exiting the first parent block with a savepoint\nif there is one, and the outermost block otherwise. Atomicity is still\nguaranteed by the outer transaction. This option should only be used if\nthe overhead of savepoints is noticeable. It has the drawback of breaking\nthe error handling described above.</p>\n<p>You may use <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> when autocommit is turned off. It will only use\nsavepoints, even for the outermost block.</p>\n</dd></dl>\n\n<aside class=\"admonition-performance-considerations admonition\">\n<p class=\"admonition-title\">Performance considerations</p>\n<p>Open transactions have a performance cost for your database server. To\nminimize this overhead, keep your transactions as short as possible. This\nis especially important if you're using <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> in long-running\nprocesses, outside of Django's request / response cycle.</p>\n</aside>\n</section>\n</section>\n<section id=\"autocommit\">\n<h2>Autocommit<a class=\"heading-anchor\" href=\"#autocommit\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"why-django-uses-autocommit\">\n<span id=\"autocommit-details\"></span><h3>Why Django uses autocommit<a class=\"heading-anchor\" href=\"#why-django-uses-autocommit\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>In the SQL standards, each SQL query starts a transaction, unless one is\nalready active. Such transactions must then be explicitly committed or rolled\nback.</p>\n<p>This isn't always convenient for application developers. To alleviate this\nproblem, most databases provide an autocommit mode. When autocommit is turned\non and no transaction is active, each SQL query gets wrapped in its own\ntransaction. In other words, not only does each such query start a\ntransaction, but the transaction also gets automatically committed or rolled\nback, depending on whether the query succeeded.</p>\n<p><span class=\"target\" id=\"index-0\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0249/\"><strong>PEP 249</strong></a>, the Python Database API Specification v2.0, requires autocommit to\nbe initially turned off. Django overrides this default and turns autocommit\non.</p>\n<p>为了避免这种情况，你可以参考 deactivate the transaction management&lt;deactivate-transaction-management&gt; ，但并不推荐这样做。</p>\n</section>\n<section id=\"deactivating-transaction-management\">\n<span id=\"deactivate-transaction-management\"></span><h3>停用事务管理<a class=\"heading-anchor\" href=\"#deactivating-transaction-management\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>You can totally disable Django's transaction management for a given database\nby setting <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-DATABASE-AUTOCOMMIT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTOCOMMIT</span></code></a> to <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> in its\nconfiguration. If you do this, Django won't enable autocommit, and won't\nperform any commits. You'll get the regular behavior of the underlying\ndatabase library.</p>\n<p>This requires you to commit explicitly every transaction, even those started\nby Django or by third-party libraries. Thus, this is best used in situations\nwhere you want to run your own transaction-controlling middleware or do\nsomething really strange.</p>\n</section>\n</section>\n<section id=\"performing-actions-after-commit\">\n<h2>提交后<a class=\"heading-anchor\" href=\"#performing-actions-after-commit\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Sometimes you need to perform an action related to the current database\ntransaction, but only if the transaction successfully commits. Examples might\ninclude a <a class=\"reference external\" href=\"http://www.celeryproject.org/\">Celery</a> task, an email notification, or a cache invalidation.</p>\n<p>Django provides the <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> function to register callback functions\nthat should be executed after a transaction is successfully committed:</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.on_commit\">\n<span class=\"sig-name descname\"><span class=\"pre\">on_commit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">func</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.on_commit\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>将任意函数（无参数）传递给 <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">transaction</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">do_something</span><span class=\"p\">():</span>\n    <span class=\"k\">pass</span>  <span class=\"c1\"># send a mail, invalidate a cache, fire off a Celery task, etc.</span>\n\n<span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">do_something</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>你也可以使用 lambda:: 包装函数</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"k\">lambda</span><span class=\"p\">:</span> <span class=\"n\">some_celery_task</span><span class=\"o\">.</span><span class=\"n\">delay</span><span class=\"p\">(</span><span class=\"s1\">&#39;arg1&#39;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>The function you pass in will be called immediately after a hypothetical\ndatabase write made where <code class=\"docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code> is called would be successfully\ncommitted.</p>\n<p>无任何活动事务时调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code> ，则回调函数会立即执行。</p>\n<p>If that hypothetical database write is instead rolled back (typically when an\nunhandled exception is raised in an <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> block), your function will\nbe discarded and never called.</p>\n<section id=\"savepoints\">\n<h3>Savepoints<a class=\"heading-anchor\" href=\"#savepoints\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Savepoints (i.e. nested <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> blocks) are handled correctly. That is,\nan <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> callable registered after a savepoint (in a nested\n<a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> block) will be called after the outer transaction is committed,\nbut not if a rollback to that savepoint or any previous savepoint occurred\nduring the transaction:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>  <span class=\"c1\"># Outer atomic, start a new transaction</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">foo</span><span class=\"p\">)</span>\n\n    <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>  <span class=\"c1\"># Inner atomic block, create a savepoint</span>\n        <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">bar</span><span class=\"p\">)</span>\n\n<span class=\"c1\"># foo() and then bar() will be called when leaving the outermost block</span>\n</code></pre></div>\n<p>On the other hand, when a savepoint is rolled back (due to an exception being\nraised), the inner callable will not be called:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>  <span class=\"c1\"># Outer atomic, start a new transaction</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">foo</span><span class=\"p\">)</span>\n\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>  <span class=\"c1\"># Inner atomic block, create a savepoint</span>\n            <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">on_commit</span><span class=\"p\">(</span><span class=\"n\">bar</span><span class=\"p\">)</span>\n            <span class=\"k\">raise</span> <span class=\"n\">SomeError</span><span class=\"p\">()</span>  <span class=\"c1\"># Raising an exception - abort the savepoint</span>\n    <span class=\"k\">except</span> <span class=\"n\">SomeError</span><span class=\"p\">:</span>\n        <span class=\"k\">pass</span>\n\n<span class=\"c1\"># foo() will be called, but not bar()</span>\n</code></pre></div>\n</section>\n<section id=\"order-of-execution\">\n<h3>执行顺序<a class=\"heading-anchor\" href=\"#order-of-execution\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>事务提交后的的回调函数执行顺序与当初注册时的顺序一致。</p>\n</section>\n<section id=\"exception-handling\">\n<h3>异常处理<a class=\"heading-anchor\" href=\"#exception-handling\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If one on-commit function within a given transaction raises an uncaught\nexception, no later registered functions in that same transaction will run.\nThis is, of course, the same behavior as if you'd executed the functions\nsequentially yourself without <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a>.</p>\n</section>\n<section id=\"timing-of-execution\">\n<h3>Timing of execution<a class=\"heading-anchor\" href=\"#timing-of-execution\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Your callbacks are executed <em>after</em> a successful commit, so a failure in a\ncallback will not cause the transaction to roll back. They are executed\nconditionally upon the success of the transaction, but they are not <em>part</em> of\nthe transaction. For the intended use cases (mail notifications, Celery tasks,\netc.), this should be fine. If it's not (if your follow-up action is so\ncritical that its failure should mean the failure of the transaction itself),\nthen you don't want to use the <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> hook. Instead, you may want\n<a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Two-phase_commit_protocol\">two-phase commit</a> such as the <a class=\"reference external\" href=\"http://initd.org/psycopg/docs/usage.html#tpc\">psycopg Two-Phase Commit protocol support</a>\nand the <a class=\"reference external\" href=\"https://www.python.org/dev/peps/pep-0249/#optional-two-phase-commit-extensions\">optional Two-Phase Commit Extensions in the Python DB-API\nspecification</a>.</p>\n<p>Callbacks are not run until autocommit is restored on the connection following\nthe commit (because otherwise any queries done in a callback would open an\nimplicit transaction, preventing the connection from going back into autocommit\nmode).</p>\n<p>When in autocommit mode and outside of an <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> block, the function\nwill run immediately, not on commit.</p>\n<p>On-commit functions only work with <a class=\"reference internal\" href=\"#managing-autocommit\"><span class=\"std std-ref\">autocommit mode</span></a>\nand the <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> (or <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-DATABASE-ATOMIC_REQUESTS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ATOMIC_REQUESTS</span></code></a>) transaction API. Calling <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> when\nautocommit is disabled and you are not within an atomic block will result in an\nerror.</p>\n</section>\n<section id=\"use-in-tests\">\n<h3>Use in tests<a class=\"heading-anchor\" href=\"#use-in-tests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django's <a class=\"reference internal\" href=\"/zh-hans/2.1/topics/testing/tools/#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TestCase</span></code></a> class wraps each test in a transaction\nand rolls back that transaction after each test, in order to provide test\nisolation. This means that no transaction is ever actually committed, thus your\n<a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> callbacks will never be run. If you need to test the results\nof an <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> callback, use a\n<a class=\"reference internal\" href=\"/zh-hans/2.1/topics/testing/tools/#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code></a> instead.</p>\n</section>\n<section id=\"why-no-rollback-hook\">\n<h3>为什么没有事务回滚钩子？<a class=\"heading-anchor\" href=\"#why-no-rollback-hook\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>事务回滚钩子相比事务提交钩子更难实现，因为各种各样的情况都可能造成隐式回滚。</p>\n<p>For instance, if your database connection is dropped because your process was\nkilled without a chance to shut down gracefully, your rollback hook will never\nrun.</p>\n<p>解决方法很简单，与其在执行事务时（原子操作）进行某项操作，当事务执行失败后再取消这项操作，不如使用 <a class=\"reference internal\" href=\"#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">on_commit()</span></code></a> 来延迟该项操作，直到事务成功后再进行操作。毕竟事务成功后你才能确保之后的操作是有意义的。</p>\n</section>\n</section>\n<section id=\"low-level-apis\">\n<h2>Low-level APIs<a class=\"heading-anchor\" href=\"#low-level-apis\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>Always prefer <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> if possible at all. It accounts for the\nidiosyncrasies of each database and prevents invalid operations.</p>\n<p>The low level APIs are only useful if you're implementing your own\ntransaction management.</p>\n</aside>\n<section id=\"managing-autocommit\">\n<span id=\"id2\"></span><h3>Autocommit<a class=\"heading-anchor\" href=\"#managing-autocommit\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django provides a straightforward API in the <a class=\"reference internal\" href=\"#module-django.db.transaction\" title=\"django.db.transaction\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.db.transaction</span></code></a>\nmodule to manage the autocommit state of each database connection.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.get_autocommit\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_autocommit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.get_autocommit\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.set_autocommit\">\n<span class=\"sig-name descname\"><span class=\"pre\">set_autocommit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">autocommit</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.set_autocommit\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>这些函数使接受一个  <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> 参数表示所要操作的数据库。如果未提供，则   Django 使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;default&quot;</span></code> 数据库。</p>\n<p>自动提交默认为开启，如果你将它关闭，自己承担后果。</p>\n<p>一旦你关闭了自动提交， Django 将无法帮助你，数据库将会按照你使用的数据库适配器的默认行为进行操作。虽然适配器的标准经过了 <span class=\"target\" id=\"index-3\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0249/\"><strong>PEP 249</strong></a> 详细规定，但不同适配器的实现方式并不总是一致的。你需要谨慎地查看你所使用的适配器的文档。</p>\n<p>在关闭自动提交之前，你必须确保当前没有活动的事务，通常你可以执行 <a class=\"reference internal\" href=\"#django.db.transaction.commit\" title=\"django.db.transaction.commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">commit()</span></code></a> 或者 <a class=\"reference internal\" href=\"#django.db.transaction.rollback\" title=\"django.db.transaction.rollback\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">rollback()</span></code></a> 函数以达到该条件。</p>\n<p>当一个原子 <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> 事务处于活动状态时， Django 将会拒绝关闭自动提交的请求，因为这样会破坏原子性。</p>\n</section>\n<section id=\"transactions\">\n<h3>事务<a class=\"heading-anchor\" href=\"#transactions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>事务是指具有原子性的一系列数据库操作。即使你的程序崩溃，数据库也会确保这些操作要么全部完成要么全部都未执行。</p>\n<p>Django doesn't provide an API to start a transaction. The expected way to\nstart a transaction is to disable autocommit with <a class=\"reference internal\" href=\"#django.db.transaction.set_autocommit\" title=\"django.db.transaction.set_autocommit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">set_autocommit()</span></code></a>.</p>\n<p>Once you're in a transaction, you can choose either to apply the changes\nyou've performed until this point with <a class=\"reference internal\" href=\"#django.db.transaction.commit\" title=\"django.db.transaction.commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">commit()</span></code></a>, or to cancel them with\n<a class=\"reference internal\" href=\"#django.db.transaction.rollback\" title=\"django.db.transaction.rollback\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">rollback()</span></code></a>. These functions are defined in <a class=\"reference internal\" href=\"#module-django.db.transaction\" title=\"django.db.transaction\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.db.transaction</span></code></a>.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.commit\">\n<span class=\"sig-name descname\"><span class=\"pre\">commit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.commit\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.rollback\">\n<span class=\"sig-name descname\"><span class=\"pre\">rollback</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.rollback\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>这些函数使接受一个  <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> 参数表示所要操作的数据库。如果未提供，则   Django 使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;default&quot;</span></code> 数据库。</p>\n<p>当一个原子 <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> 事务处于活动状态时， Django 将会拒绝进行事务提交或者事务回滚，因为这样会破坏原子性。</p>\n</section>\n<section id=\"topics-db-transactions-savepoints\">\n<span id=\"id3\"></span><h3>Savepoints<a class=\"heading-anchor\" href=\"#topics-db-transactions-savepoints\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A savepoint is a marker within a transaction that enables you to roll back\npart of a transaction, rather than the full transaction. Savepoints are\navailable with the SQLite, PostgreSQL, Oracle, and MySQL (when using the InnoDB\nstorage engine) backends. Other backends provide the savepoint functions, but\nthey're empty operations -- they don't actually do anything.</p>\n<p>Savepoints aren't especially useful if you are using autocommit, the default\nbehavior of Django. However, once you open a transaction with <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>,\nyou build up a series of database operations awaiting a commit or rollback. If\nyou issue a rollback, the entire transaction is rolled back. Savepoints\nprovide the ability to perform a fine-grained rollback, rather than the full\nrollback that would be performed by <code class=\"docutils literal notranslate\"><span class=\"pre\">transaction.rollback()</span></code>.</p>\n<p>When the <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> decorator is nested, it creates a savepoint to allow\npartial commit or rollback. You're strongly encouraged to use <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a>\nrather than the functions described below, but they're still part of the\npublic API, and there's no plan to deprecate them.</p>\n<p>Each of these functions takes a <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> argument which should be the name of\na database for which the behavior applies.  If no <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> argument is\nprovided then the <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;default&quot;</span></code> database is used.</p>\n<p>Savepoints are controlled by three functions in <a class=\"reference internal\" href=\"#module-django.db.transaction\" title=\"django.db.transaction\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.db.transaction</span></code></a>:</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.savepoint\">\n<span class=\"sig-name descname\"><span class=\"pre\">savepoint</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.savepoint\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Creates a new savepoint. This marks a point in the transaction that is\nknown to be in a &quot;good&quot; state. Returns the savepoint ID (<code class=\"docutils literal notranslate\"><span class=\"pre\">sid</span></code>).</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.savepoint_commit\">\n<span class=\"sig-name descname\"><span class=\"pre\">savepoint_commit</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sid</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.savepoint_commit\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Releases savepoint <code class=\"docutils literal notranslate\"><span class=\"pre\">sid</span></code>. The changes performed since the savepoint was\ncreated become part of the transaction.</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.savepoint_rollback\">\n<span class=\"sig-name descname\"><span class=\"pre\">savepoint_rollback</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sid</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.savepoint_rollback\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Rolls back the transaction to savepoint <code class=\"docutils literal notranslate\"><span class=\"pre\">sid</span></code>.</p>\n</dd></dl>\n\n<p>These functions do nothing if savepoints aren't supported or if the database\nis in autocommit mode.</p>\n<p>In addition, there's a utility function:</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.clean_savepoints\">\n<span class=\"sig-name descname\"><span class=\"pre\">clean_savepoints</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.clean_savepoints\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Resets the counter used to generate unique savepoint IDs.</p>\n</dd></dl>\n\n<p>The following example demonstrates the use of savepoints:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">transaction</span>\n\n<span class=\"c1\"># open a transaction</span>\n<span class=\"nd\">@transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">viewfunc</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n\n    <span class=\"n\">a</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n    <span class=\"c1\"># transaction now contains a.save()</span>\n\n    <span class=\"n\">sid</span> <span class=\"o\">=</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint</span><span class=\"p\">()</span>\n\n    <span class=\"n\">b</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n    <span class=\"c1\"># transaction now contains a.save() and b.save()</span>\n\n    <span class=\"k\">if</span> <span class=\"n\">want_to_keep_b</span><span class=\"p\">:</span>\n        <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint_commit</span><span class=\"p\">(</span><span class=\"n\">sid</span><span class=\"p\">)</span>\n        <span class=\"c1\"># open transaction still contains a.save() and b.save()</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint_rollback</span><span class=\"p\">(</span><span class=\"n\">sid</span><span class=\"p\">)</span>\n        <span class=\"c1\"># open transaction now contains only a.save()</span>\n</code></pre></div>\n<p>Savepoints may be used to recover from a database error by performing a partial\nrollback. If you're doing this inside an <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> block, the entire block\nwill still be rolled back, because it doesn't know you've handled the situation\nat a lower level! To prevent this, you can control the rollback behavior with\nthe following functions.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.get_rollback\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_rollback</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.get_rollback\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.db.transaction.set_rollback\">\n<span class=\"sig-name descname\"><span class=\"pre\">set_rollback</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">rollback</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.transaction.set_rollback\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Setting the rollback flag to <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> forces a rollback when exiting the\ninnermost atomic block. This may be useful to trigger a rollback without\nraising an exception.</p>\n<p>Setting it to <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> prevents such a rollback. Before doing that, make sure\nyou've rolled back the transaction to a known-good savepoint within the current\natomic block! Otherwise you're breaking atomicity and data corruption may\noccur.</p>\n</section>\n</section>\n<section id=\"database-specific-notes\">\n<h2>Database-specific notes<a class=\"heading-anchor\" href=\"#database-specific-notes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"savepoints-in-sqlite\">\n<span id=\"id4\"></span><h3>Savepoints in SQLite<a class=\"heading-anchor\" href=\"#savepoints-in-sqlite\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>While SQLite supports savepoints, a flaw in the design of the <a class=\"reference external\" href=\"https://docs.python.org/3/library/sqlite3.html#module-sqlite3\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">sqlite3</span></code></a>\nmodule makes them hardly usable.</p>\n<p>When autocommit is enabled, savepoints don't make sense. When it's disabled,\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/sqlite3.html#module-sqlite3\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">sqlite3</span></code></a> commits implicitly before savepoint statements. (In fact, it\ncommits before any statement other than <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">INSERT</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">UPDATE</span></code>,\n<code class=\"docutils literal notranslate\"><span class=\"pre\">DELETE</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">REPLACE</span></code>.) This bug has two consequences:</p>\n<ul class=\"simple\">\n<li><p>The low level APIs for savepoints are only usable inside a transaction ie.\ninside an <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> block.</p></li>\n<li><p>It's impossible to use <a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> when autocommit is turned off.</p></li>\n</ul>\n</section>\n<section id=\"transactions-in-mysql\">\n<h3>Transactions in MySQL<a class=\"heading-anchor\" href=\"#transactions-in-mysql\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If you're using MySQL, your tables may or may not support transactions; it\ndepends on your MySQL version and the table types you're using. (By\n&quot;table types,&quot; we mean something like &quot;InnoDB&quot; or &quot;MyISAM&quot;.) MySQL transaction\npeculiarities are outside the scope of this article, but the MySQL site has\n<a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/sql-syntax-transactions.html\">information on MySQL transactions</a>.</p>\n<p>If your MySQL setup does <em>not</em> support transactions, then Django will always\nfunction in autocommit mode: statements will be executed and committed as soon\nas they're called. If your MySQL setup <em>does</em> support transactions, Django\nwill handle transactions as explained in this document.</p>\n</section>\n<section id=\"handling-exceptions-within-postgresql-transactions\">\n<h3>Handling exceptions within PostgreSQL transactions<a class=\"heading-anchor\" href=\"#handling-exceptions-within-postgresql-transactions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>This section is relevant only if you're implementing your own transaction\nmanagement. This problem cannot occur in Django's default mode and\n<a class=\"reference internal\" href=\"#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> handles it automatically.</p>\n</aside>\n<p>Inside a transaction, when a call to a PostgreSQL cursor raises an exception\n(typically <code class=\"docutils literal notranslate\"><span class=\"pre\">IntegrityError</span></code>), all subsequent SQL in the same transaction\nwill fail with the error &quot;current transaction is aborted, queries ignored\nuntil end of transaction block&quot;. While simple use of <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> is unlikely\nto raise an exception in PostgreSQL, there are more advanced usage patterns\nwhich might, such as saving objects with unique fields, saving using the\nforce_insert/force_update flag, or invoking custom SQL.</p>\n<p>There are several ways to recover from this sort of error.</p>\n<section id=\"transaction-rollback\">\n<h4>Transaction rollback<a class=\"heading-anchor\" href=\"#transaction-rollback\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>The first option is to roll back the entire transaction. For example:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">a</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Succeeds, but may be undone by transaction rollback</span>\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    <span class=\"n\">b</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Could throw exception</span>\n<span class=\"k\">except</span> <span class=\"n\">IntegrityError</span><span class=\"p\">:</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">rollback</span><span class=\"p\">()</span>\n<span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Succeeds, but a.save() may have been undone</span>\n</code></pre></div>\n<p>Calling <code class=\"docutils literal notranslate\"><span class=\"pre\">transaction.rollback()</span></code> rolls back the entire transaction. Any\nuncommitted database operations will be lost. In this example, the changes\nmade by <code class=\"docutils literal notranslate\"><span class=\"pre\">a.save()</span></code> would be lost, even though that operation raised no error\nitself.</p>\n</section>\n<section id=\"savepoint-rollback\">\n<h4>Savepoint rollback<a class=\"heading-anchor\" href=\"#savepoint-rollback\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>You can use <a class=\"reference internal\" href=\"#topics-db-transactions-savepoints\"><span class=\"std std-ref\">savepoints</span></a> to control\nthe extent of a rollback. Before performing a database operation that could\nfail, you can set or update the savepoint; that way, if the operation fails,\nyou can roll back the single offending operation, rather than the entire\ntransaction. For example:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">a</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Succeeds, and never undone by savepoint rollback</span>\n<span class=\"n\">sid</span> <span class=\"o\">=</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint</span><span class=\"p\">()</span>\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    <span class=\"n\">b</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Could throw exception</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint_commit</span><span class=\"p\">(</span><span class=\"n\">sid</span><span class=\"p\">)</span>\n<span class=\"k\">except</span> <span class=\"n\">IntegrityError</span><span class=\"p\">:</span>\n    <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">savepoint_rollback</span><span class=\"p\">(</span><span class=\"n\">sid</span><span class=\"p\">)</span>\n<span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span> <span class=\"c1\"># Succeeds, and a.save() is never undone</span>\n</code></pre></div>\n<p>In this example, <code class=\"docutils literal notranslate\"><span class=\"pre\">a.save()</span></code> will not be undone in the case where\n<code class=\"docutils literal notranslate\"><span class=\"pre\">b.save()</span></code> raises an exception.</p>\n</section>\n</section>\n</section>","rootId":"module-django.db.transaction","toc":[{"title":"管理数据库事务","anchor":"managing-database-transactions","children":[{"title":"Django 默认的事务行为","anchor":"django-s-default-transaction-behavior","children":[]},{"title":"连结事务与 HTTP 请求","anchor":"tying-transactions-to-http-requests","children":[]},{"title":"Controlling transactions explicitly","anchor":"controlling-transactions-explicitly","children":[]}]},{"title":"Autocommit","anchor":"autocommit","children":[{"title":"Why Django uses autocommit","anchor":"why-django-uses-autocommit","children":[]},{"title":"停用事务管理","anchor":"deactivating-transaction-management","children":[]}]},{"title":"提交后","anchor":"performing-actions-after-commit","children":[{"title":"Savepoints","anchor":"savepoints","children":[]},{"title":"执行顺序","anchor":"order-of-execution","children":[]},{"title":"异常处理","anchor":"exception-handling","children":[]},{"title":"Timing of execution","anchor":"timing-of-execution","children":[]},{"title":"Use in tests","anchor":"use-in-tests","children":[]},{"title":"为什么没有事务回滚钩子？","anchor":"why-no-rollback-hook","children":[]}]},{"title":"Low-level APIs","anchor":"low-level-apis","children":[{"title":"Autocommit","anchor":"managing-autocommit","children":[]},{"title":"事务","anchor":"transactions","children":[]},{"title":"Savepoints","anchor":"topics-db-transactions-savepoints","children":[]}]},{"title":"Database-specific notes","anchor":"database-specific-notes","children":[{"title":"Savepoints in SQLite","anchor":"savepoints-in-sqlite","children":[]},{"title":"Transactions in MySQL","anchor":"transactions-in-mysql","children":[]},{"title":"Handling exceptions within PostgreSQL transactions","anchor":"handling-exceptions-within-postgresql-transactions","children":[{"title":"Transaction rollback","anchor":"transaction-rollback","children":[]},{"title":"Savepoint rollback","anchor":"savepoint-rollback","children":[]}]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Using Django","url":"/zh-hans/2.1/topics/"},{"docname":"topics/db/index","title":"模型和数据库","url":"/zh-hans/2.1/topics/db/"}],"prev":{"docname":"topics/db/sql","title":"Performing raw SQL queries","url":"/zh-hans/2.1/topics/db/sql/"},"next":{"docname":"topics/db/multi-db","title":"Multiple databases","url":"/zh-hans/2.1/topics/db/multi-db/"},"formats":{"html":"/zh-hans/2.1/topics/db/transactions/","markdown":"/zh-hans/2.1/topics/db/transactions.md","json":"/zh-hans/2.1/topics/db/transactions.json"},"source":"https://github.com/django/django/blob/stable/2.1.x/docs/topics/db/transactions.txt","official":"https://docs.djangoproject.com/zh-hans/2.1/topics/db/transactions/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}