gooderp18绿色标准版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
9.2KB

  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>61.5. Index Uniqueness Checks</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="index-locking.html" title="61.4. Index Locking Considerations" /><link rel="next" href="index-cost-estimation.html" title="61.6. Index Cost Estimation Functions" /></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">61.5. Index Uniqueness Checks</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="index-locking.html" title="61.4. Index Locking Considerations">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="indexam.html" title="Chapter 61. Index Access Method Interface Definition">Up</a></td><th width="60%" align="center">Chapter 61. Index Access Method Interface Definition</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="index-cost-estimation.html" title="61.6. Index Cost Estimation Functions">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="INDEX-UNIQUE-CHECKS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">61.5. Index Uniqueness Checks</h2></div></div></div><p>
  3. <span class="productname">PostgreSQL</span> enforces SQL uniqueness constraints
  4. using <em class="firstterm">unique indexes</em>, which are indexes that disallow
  5. multiple entries with identical keys. An access method that supports this
  6. feature sets <code class="structfield">amcanunique</code> true.
  7. (At present, only b-tree supports it.) Columns listed in the
  8. <code class="literal">INCLUDE</code> clause are not considered when enforcing
  9. uniqueness.
  10. </p><p>
  11. Because of MVCC, it is always necessary to allow duplicate entries to
  12. exist physically in an index: the entries might refer to successive
  13. versions of a single logical row. The behavior we actually want to
  14. enforce is that no MVCC snapshot could include two rows with equal
  15. index keys. This breaks down into the following cases that must be
  16. checked when inserting a new row into a unique index:
  17. </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
  18. If a conflicting valid row has been deleted by the current transaction,
  19. it's okay. (In particular, since an UPDATE always deletes the old row
  20. version before inserting the new version, this will allow an UPDATE on
  21. a row without changing the key.)
  22. </p></li><li class="listitem"><p>
  23. If a conflicting row has been inserted by an as-yet-uncommitted
  24. transaction, the would-be inserter must wait to see if that transaction
  25. commits. If it rolls back then there is no conflict. If it commits
  26. without deleting the conflicting row again, there is a uniqueness
  27. violation. (In practice we just wait for the other transaction to
  28. end and then redo the visibility check in toto.)
  29. </p></li><li class="listitem"><p>
  30. Similarly, if a conflicting valid row has been deleted by an
  31. as-yet-uncommitted transaction, the would-be inserter must wait
  32. for that transaction to commit or abort, and then repeat the test.
  33. </p></li></ul></div><p>
  34. </p><p>
  35. Furthermore, immediately before reporting a uniqueness violation
  36. according to the above rules, the access method must recheck the
  37. liveness of the row being inserted. If it is committed dead then
  38. no violation should be reported. (This case cannot occur during the
  39. ordinary scenario of inserting a row that's just been created by
  40. the current transaction. It can happen during
  41. <code class="command">CREATE UNIQUE INDEX CONCURRENTLY</code>, however.)
  42. </p><p>
  43. We require the index access method to apply these tests itself, which
  44. means that it must reach into the heap to check the commit status of
  45. any row that is shown to have a duplicate key according to the index
  46. contents. This is without a doubt ugly and non-modular, but it saves
  47. redundant work: if we did a separate probe then the index lookup for
  48. a conflicting row would be essentially repeated while finding the place to
  49. insert the new row's index entry. What's more, there is no obvious way
  50. to avoid race conditions unless the conflict check is an integral part
  51. of insertion of the new index entry.
  52. </p><p>
  53. If the unique constraint is deferrable, there is additional complexity:
  54. we need to be able to insert an index entry for a new row, but defer any
  55. uniqueness-violation error until end of statement or even later. To
  56. avoid unnecessary repeat searches of the index, the index access method
  57. should do a preliminary uniqueness check during the initial insertion.
  58. If this shows that there is definitely no conflicting live tuple, we
  59. are done. Otherwise, we schedule a recheck to occur when it is time to
  60. enforce the constraint. If, at the time of the recheck, both the inserted
  61. tuple and some other tuple with the same key are live, then the error
  62. must be reported. (Note that for this purpose, <span class="quote">“<span class="quote">live</span>”</span> actually
  63. means <span class="quote">“<span class="quote">any tuple in the index entry's HOT chain is live</span>”</span>.)
  64. To implement this, the <code class="function">aminsert</code> function is passed a
  65. <code class="literal">checkUnique</code> parameter having one of the following values:
  66. </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
  67. <code class="literal">UNIQUE_CHECK_NO</code> indicates that no uniqueness checking
  68. should be done (this is not a unique index).
  69. </p></li><li class="listitem"><p>
  70. <code class="literal">UNIQUE_CHECK_YES</code> indicates that this is a non-deferrable
  71. unique index, and the uniqueness check must be done immediately, as
  72. described above.
  73. </p></li><li class="listitem"><p>
  74. <code class="literal">UNIQUE_CHECK_PARTIAL</code> indicates that the unique
  75. constraint is deferrable. <span class="productname">PostgreSQL</span>
  76. will use this mode to insert each row's index entry. The access
  77. method must allow duplicate entries into the index, and report any
  78. potential duplicates by returning false from <code class="function">aminsert</code>.
  79. For each row for which false is returned, a deferred recheck will
  80. be scheduled.
  81. </p><p>
  82. The access method must identify any rows which might violate the
  83. unique constraint, but it is not an error for it to report false
  84. positives. This allows the check to be done without waiting for other
  85. transactions to finish; conflicts reported here are not treated as
  86. errors and will be rechecked later, by which time they may no longer
  87. be conflicts.
  88. </p></li><li class="listitem"><p>
  89. <code class="literal">UNIQUE_CHECK_EXISTING</code> indicates that this is a deferred
  90. recheck of a row that was reported as a potential uniqueness violation.
  91. Although this is implemented by calling <code class="function">aminsert</code>, the
  92. access method must <span class="emphasis"><em>not</em></span> insert a new index entry in this
  93. case. The index entry is already present. Rather, the access method
  94. must check to see if there is another live index entry. If so, and
  95. if the target row is also still live, report error.
  96. </p><p>
  97. It is recommended that in a <code class="literal">UNIQUE_CHECK_EXISTING</code> call,
  98. the access method further verify that the target row actually does
  99. have an existing entry in the index, and report error if not. This
  100. is a good idea because the index tuple values passed to
  101. <code class="function">aminsert</code> will have been recomputed. If the index
  102. definition involves functions that are not really immutable, we
  103. might be checking the wrong area of the index. Checking that the
  104. target row is found in the recheck verifies that we are scanning
  105. for the same tuple values as were used in the original insertion.
  106. </p></li></ul></div><p>
  107. </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="index-locking.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="indexam.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="index-cost-estimation.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">61.4. Index Locking Considerations </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 61.6. Index Cost Estimation Functions</td></tr></table></div></body></html>
上海开阖软件有限公司 沪ICP备12045867号-1