From 0fd4d7e5ead4ed7491015dee87bcd22e91ce93f4 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Tue, 1 Oct 2024 15:35:37 +0200 Subject: [PATCH v4 2/2] Review comments --- contrib/start-scripts/macos/README | 5 +- src/backend/access/gin/README | 110 ++++++------- src/backend/access/spgist/README | 2 +- src/backend/access/transam/README | 4 +- src/backend/regex/README | 46 +++--- src/backend/storage/lmgr/README-SSI | 240 ++++++++++++++-------------- src/backend/utils/mb/README | 16 +- src/tools/ci/README | 6 +- 8 files changed, 212 insertions(+), 217 deletions(-) diff --git a/contrib/start-scripts/macos/README b/contrib/start-scripts/macos/README index c71f98880c..5382c2e45f 100644 --- a/contrib/start-scripts/macos/README +++ b/contrib/start-scripts/macos/README @@ -15,12 +15,11 @@ if you plan to run the Postgres server under some user name other than "postgres", adjust the UserName parameter value for that. 4. Copy the modified org.postgresql.postgres.plist file into -/Library/LaunchDaemons/. You must do this as root: +/Library/LaunchDaemons/. You must do this as root because the file +will be ignored if it is not root-owned: sudo cp org.postgresql.postgres.plist /Library/LaunchDaemons - because the file will be ignored if it is not root-owned. - At this point a reboot should launch the server. But if you want to test it without rebooting, you can do diff --git a/src/backend/access/gin/README b/src/backend/access/gin/README index ccff689651..76f9b68fef 100644 --- a/src/backend/access/gin/README +++ b/src/backend/access/gin/README @@ -111,81 +111,77 @@ by building a "normal" index tuple and then modifying it.) The points to know are: * In a single-column index, a key tuple just contains the key datum, but - in a multi-column index, a key tuple contains the pair (column number, - key datum) where the column number is stored as an int2. This is needed - to support different key data types in different columns. This much of - the tuple is built by index_form_tuple according to the usual rules. - The column number (if present) can never be null, but the key datum can - be, in which case a null bitmap is present as usual. (As usual for index - tuples, the size of the null bitmap is fixed at INDEX_MAX_KEYS.) +in a multi-column index, a key tuple contains the pair (column number, +key datum) where the column number is stored as an int2. This is needed +to support different key data types in different columns. This much of +the tuple is built by index_form_tuple according to the usual rules. +The column number (if present) can never be null, but the key datum can +be, in which case a null bitmap is present as usual. (As usual for index +tuples, the size of the null bitmap is fixed at INDEX_MAX_KEYS.) * If the key datum is null (ie, IndexTupleHasNulls() is true), then - just after the nominal index data (ie, at offset IndexInfoFindDataOffset - or IndexInfoFindDataOffset + sizeof(int2)) there is a byte indicating - the "category" of the null entry. These are the possible categories: - - 1 = ordinary null key value extracted from an indexable item - 2 = placeholder for zero-key indexable item - 3 = placeholder for null indexable item - - Placeholder null entries are inserted into the index because otherwise - there would be no index entry at all for an empty or null indexable item, - which would mean that full index scans couldn't be done and various corner - cases would give wrong answers. The different categories of null entries - are treated as distinct keys by the btree, but heap itempointers for the - same category of null entry are merged into one index entry just as happens - with ordinary key entries. +just after the nominal index data (ie, at offset IndexInfoFindDataOffset +or IndexInfoFindDataOffset + sizeof(int2)) there is a byte indicating +the "category" of the null entry. These are the possible categories: + 1) ordinary null key value extracted from an indexable item + 2) placeholder for zero-key indexable item + 3) placeholder for null indexable item +Placeholder null entries are inserted into the index because otherwise +there would be no index entry at all for an empty or null indexable item, +which would mean that full index scans couldn't be done and various corner +cases would give wrong answers. The different categories of null entries +are treated as distinct keys by the btree, but heap itempointers for the +same category of null entry are merged into one index entry just as happens +with ordinary key entries. * In a key entry at the btree leaf level, at the next SHORTALIGN boundary, - there is a list of item pointers, in compressed format (see Posting List - Compression section), pointing to the heap tuples for which the indexable - items contain this key. This is called the "posting list". - - If the list would be too big for the index tuple to fit on an index page, the - ItemPointers are pushed out to a separate posting page or pages, and none - appear in the key entry itself. The separate pages are called a "posting - tree" (see below); Note that in either case, the ItemPointers associated with - a key can easily be read out in sorted order; this is relied on by the scan - algorithms. +there is a list of item pointers, in compressed format (see Posting List +Compression section), pointing to the heap tuples for which the indexable +items contain this key. This is called the "posting list". +If the list would be too big for the index tuple to fit on an index page, the +ItemPointers are pushed out to a separate posting page or pages, and none +appear in the key entry itself. The separate pages are called a "posting +tree" (see below); Note that in either case, the ItemPointers associated with +a key can easily be read out in sorted order; this is relied on by the scan +algorithms. * The index tuple header fields of a leaf key entry are abused as follows: + 1) Posting list case: -1) Posting list case: - -* ItemPointerGetBlockNumber(&itup->t_tid) contains the offset from index + - ItemPointerGetBlockNumber(&itup->t_tid) contains the offset from index tuple start to the posting list. Access macros: GinGetPostingOffset(itup) / GinSetPostingOffset(itup,n) -* ItemPointerGetOffsetNumber(&itup->t_tid) contains the number of elements + - ItemPointerGetOffsetNumber(&itup->t_tid) contains the number of elements in the posting list (number of heap itempointers). Access macros: GinGetNPosting(itup) / GinSetNPosting(itup,n) -* If IndexTupleHasNulls(itup) is true, the null category byte can be + - If IndexTupleHasNulls(itup) is true, the null category byte can be accessed/set with GinGetNullCategory(itup,gs) / GinSetNullCategory(itup,gs,c) -* The posting list can be accessed with GinGetPosting(itup) + - The posting list can be accessed with GinGetPosting(itup) -* If GinItupIsCompressed(itup), the posting list is stored in compressed + - If GinItupIsCompressed(itup), the posting list is stored in compressed format. Otherwise it is just an array of ItemPointers. New tuples are always stored in compressed format, uncompressed items can be present if the database was migrated from 9.3 or earlier version. -2) Posting tree case: + 2) Posting tree case: -* ItemPointerGetBlockNumber(&itup->t_tid) contains the index block number + - ItemPointerGetBlockNumber(&itup->t_tid) contains the index block number of the root of the posting tree. Access macros: GinGetPostingTree(itup) / GinSetPostingTree(itup, blkno) -* ItemPointerGetOffsetNumber(&itup->t_tid) contains the magic number + - ItemPointerGetOffsetNumber(&itup->t_tid) contains the magic number GIN_TREE_POSTING, which distinguishes this from the posting-list case (it's large enough that that many heap itempointers couldn't possibly fit on an index page). This value is inserted automatically by the GinSetPostingTree macro. -* If IndexTupleHasNulls(itup) is true, the null category byte can be + - If IndexTupleHasNulls(itup) is true, the null category byte can be accessed/set with GinGetNullCategory(itup,gs) / GinSetNullCategory(itup,gs,c) -* The posting list is not present and must not be accessed. + - The posting list is not present and must not be accessed. Use the macro GinIsPostingTree(itup) to determine which case applies. @@ -518,44 +514,44 @@ For compatibility, old uncompressed format is also supported. Following rules are used to handle it: * GIN_ITUP_COMPRESSED flag marks index tuples that contain a posting list. - This flag is stored in high bit of ItemPointerGetBlockNumber(&itup->t_tid). - Use GinItupIsCompressed(itup) to check the flag. +This flag is stored in high bit of ItemPointerGetBlockNumber(&itup->t_tid). +Use GinItupIsCompressed(itup) to check the flag. * Posting tree pages in the new format are marked with the GIN_COMPRESSED flag. Macros GinPageIsCompressed(page) and GinPageSetCompressed(page) are used to check and set this flag. * All scan operations check format of posting list add use corresponding code - to read its content. +to read its content. * When updating an index tuple containing an uncompressed posting list, it - will be replaced with new index tuple containing a compressed list. +will be replaced with new index tuple containing a compressed list. * When updating an uncompressed posting tree leaf page, it's compressed. * If vacuum finds some dead TIDs in uncompressed posting lists, they are - converted into compressed posting lists. This assumes that the compressed - posting list fits in the space occupied by the uncompressed list. IOW, we - assume that the compressed version of the page, with the dead items removed, - takes less space than the old uncompressed version. +converted into compressed posting lists. This assumes that the compressed +posting list fits in the space occupied by the uncompressed list. IOW, we +assume that the compressed version of the page, with the dead items removed, +takes less space than the old uncompressed version. Limitations ----------- -* Gin doesn't use scan->kill_prior_tuple & scan->ignore_killed_tuples -* Gin searches entries only by equality matching, or simple range - matching using the "partial match" feature. + * Gin doesn't use scan->kill_prior_tuple & scan->ignore_killed_tuples + * Gin searches entries only by equality matching, or simple range + matching using the "partial match" feature. TODO ---- Nearest future: -* Opclasses for more types (no programming, just many catalog changes) + * Opclasses for more types (no programming, just many catalog changes) Distant future: -* Replace B-tree of entries to something like GiST + * Replace B-tree of entries to something like GiST Authors ------- diff --git a/src/backend/access/spgist/README b/src/backend/access/spgist/README index 2b890e4f8e..b55bebf438 100644 --- a/src/backend/access/spgist/README +++ b/src/backend/access/spgist/README @@ -160,7 +160,7 @@ the following notation, where tuple's id is just for discussion (no such id is actually stored): inner tuple: {tuple id}(prefix string)[ comma separated list of node labels ] -leaf tuple: {tuple id}< value > +leaf tuple: {tuple id}(value) Suppose we need to insert string 'www.gogo.com' into inner tuple diff --git a/src/backend/access/transam/README b/src/backend/access/transam/README index 62015da1fe..7adab8a06b 100644 --- a/src/backend/access/transam/README +++ b/src/backend/access/transam/README @@ -90,7 +90,7 @@ commit or abort processing. Furthermore, suppose the "SELECT * FROM foo" caused an abort condition. In this case AbortCurrentTransaction is called, and the transaction is put in aborted state. In this state, any user input is ignored except for -transaction-termination statements, or ROLLBACK TO commands. +transaction-termination statements, or ROLLBACK TO SAVEPOINT commands. Transaction aborts can occur in two ways: @@ -171,7 +171,7 @@ CommitTransactionCommand, the real work is done. The main point of doing things this way is that if we get an error while popping state stack entries, the remaining stack entries still show what we need to do to finish up. -In the case of ROLLBACK TO < savepoint >, we abort all the subtransactions up +In the case of ROLLBACK TO SAVEPOINT, we abort all the subtransactions up through the one identified by the savepoint name, and then re-create that subtransaction level with the same name. So it's a completely new subtransaction as far as the internals are concerned. diff --git a/src/backend/regex/README b/src/backend/regex/README index a0d45589b6..d8528b2af8 100644 --- a/src/backend/regex/README +++ b/src/backend/regex/README @@ -10,11 +10,11 @@ General source-file layout There are six separately-compilable source files, five of which expose exactly one exported function apiece: - regcomp.c pg_regcomp - regexec.c pg_regexec - regerror.c pg_regerror - regfree.c pg_regfree - regprefix.c pg_regprefix +* regcomp.c pg_regcomp +* regexec.c pg_regexec +* regerror.c pg_regerror +* regfree.c pg_regfree +* regprefix.c pg_regprefix (The pg_ prefixes were added by the Postgres project to distinguish this library version from any similar one that might be present on a particular @@ -40,19 +40,19 @@ structs.) What's where in src/backend/regex/: - regcomp.c Top-level regex compilation code - regc_color.c Color map management - regc_cvec.c Character vector (cvec) management - regc_lex.c Lexer - regc_nfa.c NFA handling - regc_locale.c Application-specific locale code from Tcl project - regc_pg_locale.c Postgres-added application-specific locale code - regexec.c Top-level regex execution code - rege_dfa.c DFA creation and execution - regerror.c pg_regerror: generate text for a regex error code - regfree.c pg_regfree: API to free a no-longer-needed regex_t - regexport.c Functions for extracting info from a regex_t - regprefix.c Code for extracting a common prefix from a regex_t +* regcomp.c Top-level regex compilation code +* regc_color.c Color map management +* regc_cvec.c Character vector (cvec) management +* regc_lex.c Lexer +* regc_nfa.c NFA handling +* regc_locale.c Application-specific locale code from Tcl project +* regc_pg_locale.c Postgres-added application-specific locale code +* regexec.c Top-level regex execution code +* rege_dfa.c DFA creation and execution +* regerror.c pg_regerror: generate text for a regex error code +* regfree.c pg_regfree: API to free a no-longer-needed regex_t +* regexport.c Functions for extracting info from a regex_t +* regprefix.c Code for extracting a common prefix from a regex_t The locale-specific code is concerned primarily with case-folding and with expanding locale-specific character classes, such as [[:alnum:]]. It @@ -60,11 +60,11 @@ really needs refactoring if this is ever to become a standalone library. The header files for the library are in src/include/regex/: - regcustom.h Customizes library for particular application - regerrs.h Error message list - regex.h Exported API - regexport.h Exported API for regexport.c - regguts.h Internals declarations +* regcustom.h Customizes library for particular application +* regerrs.h Error message list +* regex.h Exported API +* regexport.h Exported API for regexport.c +* regguts.h Internals declarations DFAs, NFAs, and all that diff --git a/src/backend/storage/lmgr/README-SSI b/src/backend/storage/lmgr/README-SSI index be9a6f96cf..016a48c408 100644 --- a/src/backend/storage/lmgr/README-SSI +++ b/src/backend/storage/lmgr/README-SSI @@ -200,54 +200,54 @@ PostgreSQL Implementation ------------------------- * Since this technique is based on Snapshot Isolation (SI), those - areas in PostgreSQL which don't use SI can't be brought under SSI. - This includes system tables, temporary tables, sequences, hint bit - rewrites, etc. SSI can not eliminate existing anomalies in these - areas. +areas in PostgreSQL which don't use SI can't be brought under SSI. +This includes system tables, temporary tables, sequences, hint bit +rewrites, etc. SSI can not eliminate existing anomalies in these +areas. * Any transaction which is run at a transaction isolation level - other than SERIALIZABLE will not be affected by SSI. If you want to - enforce business rules through SSI, all transactions should be run at - the SERIALIZABLE transaction isolation level, and that should - probably be set as the default. +other than SERIALIZABLE will not be affected by SSI. If you want to +enforce business rules through SSI, all transactions should be run at +the SERIALIZABLE transaction isolation level, and that should +probably be set as the default. * If all transactions are run at the SERIALIZABLE transaction - isolation level, business rules can be enforced in triggers or - application code without ever having a need to acquire an explicit - lock or to use SELECT FOR SHARE or SELECT FOR UPDATE. +isolation level, business rules can be enforced in triggers or +application code without ever having a need to acquire an explicit +lock or to use SELECT FOR SHARE or SELECT FOR UPDATE. * Those who want to continue to use snapshot isolation without - the additional protections of SSI (and the associated costs of - enforcing those protections), can use the REPEATABLE READ transaction - isolation level. This level retains its legacy behavior, which - is identical to the old SERIALIZABLE implementation and fully - consistent with the standard's requirements for the REPEATABLE READ - transaction isolation level. +the additional protections of SSI (and the associated costs of +enforcing those protections), can use the REPEATABLE READ transaction +isolation level. This level retains its legacy behavior, which +is identical to the old SERIALIZABLE implementation and fully +consistent with the standard's requirements for the REPEATABLE READ +transaction isolation level. * Performance under this SSI implementation will be significantly - improved if transactions which don't modify permanent tables are - declared to be READ ONLY before they begin reading data. +improved if transactions which don't modify permanent tables are +declared to be READ ONLY before they begin reading data. * Performance under SSI will tend to degrade more rapidly with a - large number of active database transactions than under less strict - isolation levels. Limiting the number of active transactions through - use of a connection pool or similar techniques may be necessary to - maintain good performance. +large number of active database transactions than under less strict +isolation levels. Limiting the number of active transactions through +use of a connection pool or similar techniques may be necessary to +maintain good performance. * Any transaction which must be rolled back to prevent - serialization anomalies will fail with SQLSTATE 40001, which has a - standard meaning of "serialization failure". +serialization anomalies will fail with SQLSTATE 40001, which has a +standard meaning of "serialization failure". * This SSI implementation makes an effort to choose the - transaction to be canceled such that an immediate retry of the - transaction will not fail due to conflicts with exactly the same - transactions. Pursuant to this goal, no transaction is canceled - until one of the other transactions in the set of conflicts which - could generate an anomaly has successfully committed. This is - conceptually similar to how write conflicts are handled. To fully - implement this guarantee there needs to be a way to roll back the - active transaction for another process with a serialization failure - SQLSTATE, even if it is "idle in transaction". +transaction to be canceled such that an immediate retry of the +transaction will not fail due to conflicts with exactly the same +transactions. Pursuant to this goal, no transaction is canceled +until one of the other transactions in the set of conflicts which +could generate an anomaly has successfully committed. This is +conceptually similar to how write conflicts are handled. To fully +implement this guarantee there needs to be a way to roll back the +active transaction for another process with a serialization failure +SQLSTATE, even if it is "idle in transaction". Predicate Locking @@ -306,20 +306,20 @@ Predicate locks will be acquired for the heap based on the following: * For a table scan, the entire relation will be locked. * Each tuple read which is visible to the reading transaction - will be locked, whether or not it meets selection criteria; except - that there is no need to acquire an SIREAD lock on a tuple when the - transaction already holds a write lock on any tuple representing the - row, since a rw-conflict would also create a ww-dependency which - has more aggressive enforcement and thus will prevent any anomaly. +will be locked, whether or not it meets selection criteria; except +that there is no need to acquire an SIREAD lock on a tuple when the +transaction already holds a write lock on any tuple representing the +row, since a rw-conflict would also create a ww-dependency which +has more aggressive enforcement and thus will prevent any anomaly. * Modifying a heap tuple creates a rw-conflict with any transaction - that holds a SIREAD lock on that tuple, or on the page or relation - that contains it. +that holds a SIREAD lock on that tuple, or on the page or relation +that contains it. * Inserting a new tuple creates a rw-conflict with any transaction - holding a SIREAD lock on the entire relation. It doesn't conflict with - page-level locks, because page-level locks are only used to aggregate - tuple locks. Unlike index page locks, they don't lock "gaps" on the page. +holding a SIREAD lock on the entire relation. It doesn't conflict with +page-level locks, because page-level locks are only used to aggregate +tuple locks. Unlike index page locks, they don't lock "gaps" on the page. Index AM implementations @@ -347,59 +347,59 @@ false positives, they should be minimized for performance reasons. Several optimizations are possible, though not all are implemented yet: * An index scan which is just finding the right position for an - index insertion or deletion need not acquire a predicate lock. +index insertion or deletion need not acquire a predicate lock. * An index scan which is comparing for equality on the entire key - for a unique index need not acquire a predicate lock as long as a key - is found corresponding to a visible tuple which has not been modified - by another transaction -- there are no "between or around" gaps to - cover. +for a unique index need not acquire a predicate lock as long as a key +is found corresponding to a visible tuple which has not been modified +by another transaction -- there are no "between or around" gaps to +cover. * As long as built-in foreign key enforcement continues to use - its current "special tricks" to deal with MVCC issues, predicate - locks should not be needed for scans done by enforcement code. +its current "special tricks" to deal with MVCC issues, predicate +locks should not be needed for scans done by enforcement code. * If a search determines that no rows can be found regardless of - index contents because the search conditions are contradictory (e.g., - x = 1 AND x = 2), then no predicate lock is needed. +index contents because the search conditions are contradictory (e.g., +x = 1 AND x = 2), then no predicate lock is needed. Other index AM implementation considerations: * For an index AM that doesn't have support for predicate locking, - we just acquire a predicate lock on the whole index for any search. +we just acquire a predicate lock on the whole index for any search. * B-tree index searches acquire predicate locks only on the - index *leaf* pages needed to lock the appropriate index range. If, - however, a search discovers that no root page has yet been created, a - predicate lock on the index relation is required. +index *leaf* pages needed to lock the appropriate index range. If, +however, a search discovers that no root page has yet been created, a +predicate lock on the index relation is required. * Like a B-tree, GIN searches acquire predicate locks only on the - leaf pages of entry tree. When performing an equality scan, and an - entry has a posting tree, the posting tree root is locked instead, to - lock only that key value. However, fastupdate=on postpones the - insertion of tuples into index structure by temporarily storing them - into pending list. That makes us unable to detect r-w conflicts using - page-level locks. To cope with that, insertions to the pending list - conflict with all scans. +leaf pages of entry tree. When performing an equality scan, and an +entry has a posting tree, the posting tree root is locked instead, to +lock only that key value. However, fastupdate=on postpones the +insertion of tuples into index structure by temporarily storing them +into pending list. That makes us unable to detect r-w conflicts using +page-level locks. To cope with that, insertions to the pending list +conflict with all scans. * GiST searches can determine that there are no matches at any - level of the index, so we acquire predicate lock at each index - level during a GiST search. An index insert at the leaf level can - then be trusted to ripple up to all levels and locations where - conflicting predicate locks may exist. In case there is a page split, - we need to copy predicate lock from the original page to all the new - pages. +level of the index, so we acquire predicate lock at each index +level during a GiST search. An index insert at the leaf level can +then be trusted to ripple up to all levels and locations where +conflicting predicate locks may exist. In case there is a page split, +we need to copy predicate lock from the original page to all the new +pages. * Hash index searches acquire predicate locks on the primary - page of a bucket. It acquires a lock on both the old and new buckets - for scans that happen concurrently with page splits. During a bucket - split, a predicate lock is copied from the primary page of an old - bucket to the primary page of a new bucket. +page of a bucket. It acquires a lock on both the old and new buckets +for scans that happen concurrently with page splits. During a bucket +split, a predicate lock is copied from the primary page of an old +bucket to the primary page of a new bucket. * The effects of page splits, overflows, consolidations, and - removals must be carefully reviewed to ensure that predicate locks - aren't "lost" during those operations, or kept with pages which could - get re-used for different parts of the index. +removals must be carefully reviewed to ensure that predicate locks +aren't "lost" during those operations, or kept with pages which could +get re-used for different parts of the index. Innovations @@ -448,34 +448,34 @@ Differences from the implementation described in the papers are listed below. * New structures needed to be created in shared memory to track - the proper information for serializable transactions and their SIREAD - locks. +the proper information for serializable transactions and their SIREAD +locks. * Because PostgreSQL does not have the same concept of an "oldest - transaction ID" for all serializable transactions as assumed in the - Cahill thesis, we track the oldest snapshot xmin among serializable - transactions, and a count of how many active transactions use that - xmin. When the count hits zero we find the new oldest xmin and run a - clean-up based on that. +transaction ID" for all serializable transactions as assumed in the +Cahill thesis, we track the oldest snapshot xmin among serializable +transactions, and a count of how many active transactions use that +xmin. When the count hits zero we find the new oldest xmin and run a +clean-up based on that. * Because reads in a subtransaction may cause that subtransaction - to roll back, thereby affecting what is written by the top level - transaction, predicate locks must survive a subtransaction rollback. - As a consequence, all xid usage in SSI, including predicate locking, - is based on the top level xid. When looking at an xid that comes - from a tuple's xmin or xmax, for example, we always call - SubTransGetTopmostTransaction() before doing much else with it. +to roll back, thereby affecting what is written by the top level +transaction, predicate locks must survive a subtransaction rollback. +As a consequence, all xid usage in SSI, including predicate locking, +is based on the top level xid. When looking at an xid that comes +from a tuple's xmin or xmax, for example, we always call +SubTransGetTopmostTransaction() before doing much else with it. * PostgreSQL does not use "update in place" with a rollback log - for its MVCC implementation. Where possible it uses "HOT" updates on - the same page (if there is room and no indexed value is changed). - For non-HOT updates the old tuple is expired in place and a new tuple - is inserted at a new location. Because of this difference, a tuple - lock in PostgreSQL doesn't automatically lock any other versions of a - row. We don't try to copy or expand a tuple lock to any other - versions of the row, based on the following proof that any additional - serialization failures we would get from that would be false - positives: +for its MVCC implementation. Where possible it uses "HOT" updates on +the same page (if there is room and no indexed value is changed). +For non-HOT updates the old tuple is expired in place and a new tuple +is inserted at a new location. Because of this difference, a tuple +lock in PostgreSQL doesn't automatically lock any other versions of a +row. We don't try to copy or expand a tuple lock to any other +versions of the row, based on the following proof that any additional +serialization failures we would get from that would be false +positives: - If transaction T1 reads a row version (thus acquiring a predicate lock on it) and a second transaction T2 updates that row @@ -595,33 +595,33 @@ This is intended to be the place to record specific issues which need more detailed review or analysis. * WAL file replay. While serializable implementations using S2PL - can guarantee that the write-ahead log contains commits in a sequence - consistent with some serial execution of serializable transactions, - SSI cannot make that guarantee. While the WAL replay is no less - consistent than under snapshot isolation, it is possible that under - PITR recovery or hot standby a database could reach a readable state - where some transactions appear before other transactions which would - have had to precede them to maintain serializable consistency. In - essence, if we do nothing, WAL replay will be at snapshot isolation - even for serializable transactions. Is this OK? If not, how do we - address it? +can guarantee that the write-ahead log contains commits in a sequence +consistent with some serial execution of serializable transactions, +SSI cannot make that guarantee. While the WAL replay is no less +consistent than under snapshot isolation, it is possible that under +PITR recovery or hot standby a database could reach a readable state +where some transactions appear before other transactions which would +have had to precede them to maintain serializable consistency. In +essence, if we do nothing, WAL replay will be at snapshot isolation +even for serializable transactions. Is this OK? If not, how do we +address it? * External replication. Look at how this impacts external - replication solutions, like Postgres-R, Slony, pgpool, HS/SR, etc. - This is related to the "WAL file replay" issue. +replication solutions, like Postgres-R, Slony, pgpool, HS/SR, etc. +This is related to the "WAL file replay" issue. * UNIQUE btree search for equality on all columns. Since a search - of a UNIQUE index using equality tests on all columns will lock the - heap tuple if an entry is found, it appears that there is no need to - get a predicate lock on the index in that case. A predicate lock is - still needed for such a search if a matching index entry which points - to a visible tuple is not found. +of a UNIQUE index using equality tests on all columns will lock the +heap tuple if an entry is found, it appears that there is no need to +get a predicate lock on the index in that case. A predicate lock is +still needed for such a search if a matching index entry which points +to a visible tuple is not found. * Minimize touching of shared memory. Should lists in shared - memory push entries which have just been returned to the front of the - available list, so they will be popped back off soon and some memory - might never be touched, or should we keep adding returned items to - the end of the available list? +memory push entries which have just been returned to the front of the +available list, so they will be popped back off soon and some memory +might never be touched, or should we keep adding returned items to +the end of the available list? References diff --git a/src/backend/utils/mb/README b/src/backend/utils/mb/README index afbe4c65d1..64de5b63ab 100644 --- a/src/backend/utils/mb/README +++ b/src/backend/utils/mb/README @@ -3,18 +3,18 @@ src/backend/utils/mb/README Encodings ========= - conv.c static functions and a public table for code conversion - mbutils.c public functions for the backend only. - stringinfo_mb.c public backend-only multibyte-aware stringinfo functions - wstrcmp.c strcmp for mb - wstrncmp.c strncmp for mb +* conv.c static functions and a public table for code conversion +* mbutils.c public functions for the backend only. +* stringinfo_mb.c public backend-only multibyte-aware stringinfo functions +* wstrcmp.c strcmp for mb +* wstrncmp.c strncmp for mb See also in src/common/: - encnames.c public functions for encoding names - wchar.c mostly static functions and a public table for mb string and +* encnames.c public functions for encoding names +* wchar.c mostly static functions and a public table for mb string and multibyte conversion Introduction ------------ - http://www.cprogramming.com/tutorial/unicode.html +http://www.cprogramming.com/tutorial/unicode.html diff --git a/src/tools/ci/README b/src/tools/ci/README index e82073ff8a..f17ff3cbf7 100644 --- a/src/tools/ci/README +++ b/src/tools/ci/README @@ -35,7 +35,7 @@ See also https://cirrus-ci.org/guide/quick-start/ Once enabled on a repository, future commits and pull-requests in that repository will automatically trigger CI builds. These are visible from the commit history / PRs, and can also be viewed in the cirrus-ci UI at -https://cirrus-ci.com/github/< username >/< reponame >/ +https://cirrus-ci.com/github/username/reponame/ Hint: all build log files are uploaded to cirrus-ci and can be downloaded from the "Artifacts" section from the cirrus-ci UI after clicking into a @@ -52,7 +52,7 @@ would need to build its own set of containers, which would be wasteful (both in space and time. These images are built, on a daily basis, from the specifications in -github.com/anarazel/pg-vm-images/ +https://github.com/anarazel/pg-vm-images/ Controlling CI via commit messages @@ -74,7 +74,7 @@ When running a lot of tests in a repository, cirrus-ci's free credits do not suffice. In those cases a repository can be configured to use other infrastructure for running tests. To do so, the REPO_CI_CONFIG_GIT_URL variable can be configured for the repository in the cirrus-ci web interface, -at https://cirrus-ci.com/github/< user or organization >. The file referenced +at https://cirrus-ci.com/github/user_or_organization. The file referenced (see https://cirrus-ci.org/guide/programming-tasks/#fs) by the variable can overwrite the default execution method for different operating systems, defined in .cirrus.yml, by redefining the relevant yaml anchors. -- 2.39.3 (Apple Git-146)