gooderp18绿色标准版
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

107 lines
8.0KB

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>45.8. Explicit Subtransactions</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets V1.79.1" /><link rel="prev" href="plpython-database.html" title="45.7. Database Access" /><link rel="next" href="plpython-transactions.html" title="45.9. Transaction Management" /></head><body><div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">45.8. Explicit Subtransactions</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="plpython-database.html" title="45.7. Database Access">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="plpython.html" title="Chapter 45. PL/Python - Python Procedural Language">Up</a></td><th width="60%" align="center">Chapter 45. PL/Python - Python Procedural Language</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 12.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="plpython-transactions.html" title="45.9. Transaction Management">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="PLPYTHON-SUBTRANSACTION"><div class="titlepage"><div><div><h2 class="title" style="clear: both">45.8. Explicit Subtransactions</h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="plpython-subtransaction.html#id-1.8.11.16.3">45.8.1. Subtransaction Context Managers</a></span></dt><dt><span class="sect2"><a href="plpython-subtransaction.html#id-1.8.11.16.4">45.8.2. Older Python Versions</a></span></dt></dl></div><p>
  3. Recovering from errors caused by database access as described in
  4. <a class="xref" href="plpython-database.html#PLPYTHON-TRAPPING" title="45.7.2. Trapping Errors">Section 45.7.2</a> can lead to an undesirable
  5. situation where some operations succeed before one of them fails,
  6. and after recovering from that error the data is left in an
  7. inconsistent state. PL/Python offers a solution to this problem in
  8. the form of explicit subtransactions.
  9. </p><div class="sect2" id="id-1.8.11.16.3"><div class="titlepage"><div><div><h3 class="title">45.8.1. Subtransaction Context Managers</h3></div></div></div><p>
  10. Consider a function that implements a transfer between two
  11. accounts:
  12. </p><pre class="programlisting">
  13. CREATE FUNCTION transfer_funds() RETURNS void AS $$
  14. try:
  15. plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'")
  16. plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'")
  17. except plpy.SPIError, e:
  18. result = "error transferring funds: %s" % e.args
  19. else:
  20. result = "funds transferred correctly"
  21. plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
  22. plpy.execute(plan, [result])
  23. $$ LANGUAGE plpythonu;
  24. </pre><p>
  25. If the second <code class="literal">UPDATE</code> statement results in an
  26. exception being raised, this function will report the error, but
  27. the result of the first <code class="literal">UPDATE</code> will
  28. nevertheless be committed. In other words, the funds will be
  29. withdrawn from Joe's account, but will not be transferred to
  30. Mary's account.
  31. </p><p>
  32. To avoid such issues, you can wrap your
  33. <code class="literal">plpy.execute</code> calls in an explicit
  34. subtransaction. The <code class="literal">plpy</code> module provides a
  35. helper object to manage explicit subtransactions that gets created
  36. with the <code class="literal">plpy.subtransaction()</code> function.
  37. Objects created by this function implement the
  38. <a class="ulink" href="https://docs.python.org/library/stdtypes.html#context-manager-types" target="_top">
  39. context manager interface</a>. Using explicit subtransactions
  40. we can rewrite our function as:
  41. </p><pre class="programlisting">
  42. CREATE FUNCTION transfer_funds2() RETURNS void AS $$
  43. try:
  44. with plpy.subtransaction():
  45. plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'")
  46. plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'")
  47. except plpy.SPIError, e:
  48. result = "error transferring funds: %s" % e.args
  49. else:
  50. result = "funds transferred correctly"
  51. plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
  52. plpy.execute(plan, [result])
  53. $$ LANGUAGE plpythonu;
  54. </pre><p>
  55. Note that the use of <code class="literal">try/catch</code> is still
  56. required. Otherwise the exception would propagate to the top of
  57. the Python stack and would cause the whole function to abort with
  58. a <span class="productname">PostgreSQL</span> error, so that the
  59. <code class="literal">operations</code> table would not have any row
  60. inserted into it. The subtransaction context manager does not
  61. trap errors, it only assures that all database operations executed
  62. inside its scope will be atomically committed or rolled back. A
  63. rollback of the subtransaction block occurs on any kind of
  64. exception exit, not only ones caused by errors originating from
  65. database access. A regular Python exception raised inside an
  66. explicit subtransaction block would also cause the subtransaction
  67. to be rolled back.
  68. </p></div><div class="sect2" id="id-1.8.11.16.4"><div class="titlepage"><div><div><h3 class="title">45.8.2. Older Python Versions</h3></div></div></div><p>
  69. Context managers syntax using the <code class="literal">with</code> keyword
  70. is available by default in Python 2.6. If using PL/Python with an
  71. older Python version, it is still possible to use explicit
  72. subtransactions, although not as transparently. You can call the
  73. subtransaction manager's <code class="literal">__enter__</code> and
  74. <code class="literal">__exit__</code> functions using the
  75. <code class="literal">enter</code> and <code class="literal">exit</code> convenience
  76. aliases. The example function that transfers funds could be
  77. written as:
  78. </p><pre class="programlisting">
  79. CREATE FUNCTION transfer_funds_old() RETURNS void AS $$
  80. try:
  81. subxact = plpy.subtransaction()
  82. subxact.enter()
  83. try:
  84. plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'")
  85. plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'")
  86. except:
  87. import sys
  88. subxact.exit(*sys.exc_info())
  89. raise
  90. else:
  91. subxact.exit(None, None, None)
  92. except plpy.SPIError, e:
  93. result = "error transferring funds: %s" % e.args
  94. else:
  95. result = "funds transferred correctly"
  96. plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
  97. plpy.execute(plan, [result])
  98. $$ LANGUAGE plpythonu;
  99. </pre><p>
  100. </p><div class="note"><h3 class="title">Note</h3><p>
  101. Although context managers were implemented in Python 2.5, to use
  102. the <code class="literal">with</code> syntax in that version you need to
  103. use a <a class="ulink" href="https://docs.python.org/release/2.5/ref/future.html" target="_top">future
  104. statement</a>. Because of implementation details, however,
  105. you cannot use future statements in PL/Python functions.
  106. </p></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="plpython-database.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="plpython.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="plpython-transactions.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">45.7. Database Access </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 45.9. Transaction Management</td></tr></table></div></body></html>
上海开阖软件有限公司 沪ICP备12045867号-1