gooderp18绿色标准版
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

67 行
5.8KB

  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>43.9. Explicit Subtransactions in PL/Tcl</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="pltcl-error-handling.html" title="43.8. Error Handling in PL/Tcl" /><link rel="next" href="pltcl-transactions.html" title="43.10. 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">43.9. Explicit Subtransactions in PL/Tcl</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="pltcl-error-handling.html" title="43.8. Error Handling in PL/Tcl">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="pltcl.html" title="Chapter 43. PL/Tcl - Tcl Procedural Language">Up</a></td><th width="60%" align="center">Chapter 43. PL/Tcl - Tcl 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="pltcl-transactions.html" title="43.10. Transaction Management">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="PLTCL-SUBTRANSACTIONS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">43.9. Explicit Subtransactions in PL/Tcl</h2></div></div></div><a id="id-1.8.9.13.2" class="indexterm"></a><p>
  3. Recovering from errors caused by database access as described in
  4. <a class="xref" href="pltcl-error-handling.html" title="43.8. Error Handling in PL/Tcl">Section 43.8</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/Tcl offers a solution to this problem in
  8. the form of explicit subtransactions.
  9. </p><p>
  10. Consider a function that implements a transfer between two accounts:
  11. </p><pre class="programlisting">
  12. CREATE FUNCTION transfer_funds() RETURNS void AS $$
  13. if [catch {
  14. spi_exec "UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'"
  15. spi_exec "UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'"
  16. } errormsg] {
  17. set result [format "error transferring funds: %s" $errormsg]
  18. } else {
  19. set result "funds transferred successfully"
  20. }
  21. spi_exec "INSERT INTO operations (result) VALUES ('[quote $result]')"
  22. $$ LANGUAGE pltcl;
  23. </pre><p>
  24. If the second <code class="command">UPDATE</code> statement results in an
  25. exception being raised, this function will log the failure, but
  26. the result of the first <code class="command">UPDATE</code> will
  27. nevertheless be committed. In other words, the funds will be
  28. withdrawn from Joe's account, but will not be transferred to
  29. Mary's account. This happens because each <code class="function">spi_exec</code>
  30. is a separate subtransaction, and only one of those subtransactions
  31. got rolled back.
  32. </p><p>
  33. To handle such cases, you can wrap multiple database operations in an
  34. explicit subtransaction, which will succeed or roll back as a whole.
  35. PL/Tcl provides a <code class="function">subtransaction</code> command to manage
  36. this. We can rewrite our function as:
  37. </p><pre class="programlisting">
  38. CREATE FUNCTION transfer_funds2() RETURNS void AS $$
  39. if [catch {
  40. subtransaction {
  41. spi_exec "UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'"
  42. spi_exec "UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'"
  43. }
  44. } errormsg] {
  45. set result [format "error transferring funds: %s" $errormsg]
  46. } else {
  47. set result "funds transferred successfully"
  48. }
  49. spi_exec "INSERT INTO operations (result) VALUES ('[quote $result]')"
  50. $$ LANGUAGE pltcl;
  51. </pre><p>
  52. Note that use of <code class="function">catch</code> is still required for this
  53. purpose. Otherwise the error would propagate to the top level of the
  54. function, preventing the desired insertion into
  55. the <code class="structname">operations</code> table.
  56. The <code class="function">subtransaction</code> command does not trap errors, it
  57. only assures that all database operations executed inside its scope will
  58. be rolled back together when an error is reported.
  59. </p><p>
  60. A rollback of an explicit subtransaction occurs on any error reported
  61. by the contained Tcl code, not only errors originating from database
  62. access. Thus a regular Tcl exception raised inside
  63. a <code class="function">subtransaction</code> command will also cause the
  64. subtransaction to be rolled back. However, non-error exits out of the
  65. contained Tcl code (for instance, due to <code class="function">return</code>) do
  66. not cause a rollback.
  67. </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="pltcl-error-handling.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="pltcl.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="pltcl-transactions.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">43.8. Error Handling in PL/Tcl </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 43.10. Transaction Management</td></tr></table></div></body></html>
上海开阖软件有限公司 沪ICP备12045867号-1