From c0b4b42c92b7f3243959de6241349a54444e1bb2 Mon Sep 17 00:00:00 2001 From: "Vadim B. Mikheev" Date: Tue, 8 Jun 1999 20:01:01 +0000 Subject: [PATCH] MVCC updation. --- doc/src/sgml/ref/lock.sgml | 219 +++++++++++++++++++++++++++++-------- doc/src/sgml/ref/set.sgml | 33 +++--- 2 files changed, 186 insertions(+), 66 deletions(-) diff --git a/doc/src/sgml/ref/lock.sgml b/doc/src/sgml/ref/lock.sgml index 02245c1bfa..48d462ab29 100644 --- a/doc/src/sgml/ref/lock.sgml +++ b/doc/src/sgml/ref/lock.sgml @@ -25,7 +25,7 @@ LOCK [ TABLE ] table IN SHARE ROW E - 1998-09-01 + 1999-06-09 Inputs @@ -46,73 +46,140 @@ LOCK [ TABLE ] <replaceable class="PARAMETER">table</replaceable> IN SHARE ROW E <varlistentry> <term> - SHARE MODE + ACCESS SHARE MODE </term> <listitem> + <note> <para> + This lock mode is acquired automatically over tables being queried. + <productname>Postgres</productname> releases automatically acquired + ACCESS SHARE locks after statement is done. + </para> + </note> + + <para> + This is the less restrictive lock mode which conflicts with + ACCESS EXCLUSIVE mode only. It's intended to protect table being + queried from concurrent <command>ALTER TABLE</command>, + <command>DROP TABLE</command> and <command>VACUUM</command> + statements over the same table. </para> </listitem> </varlistentry> <varlistentry> <term> - EXCLUSIVE MODE + ROW SHARE MODE </term> <listitem> + <note> <para> + Automatically acquired by <command>SELECT FOR UPDATE</command> statement. + </para> + </note> + + <para> + Conflicts with EXCLUSIVE and ACCESS EXCLUSIVE lock modes. </para> </listitem> </varlistentry> <varlistentry> <term> - ROW SHARE MODE + ROW EXCLUSIVE MODE </term> <listitem> + <note> <para> + Automatically acquired by <command>UPDATE</command>, + <command>DELETE</command>, <command>INSERT</command> statements. + </para> + </note> + + <para> + Conflicts with SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE and + ACCESS EXCLUSIVE modes. Generally means that a transaction + updated/inserted some tuples in a table. </para> </listitem> </varlistentry> <varlistentry> <term> - ROW EXCLUSIVE MODE + SHARE MODE </term> <listitem> + <note> <para> + Automatically acquired by <command>CREATE INDEX</command> statement. + </para> + </note> + + <para> + Conflicts with ROW EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE and + ACCESS EXCLUSIVE modes. This mode protects a table against + concurrent updates. </para> </listitem> </varlistentry> <varlistentry> <term> - ACCESS SHARE MODE + SHARE ROW EXCLUSIVE MODE </term> <listitem> - <para> + + <para> + Conflicts with ROW EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, + EXCLUSIVE and ACCESS EXCLUSIVE modes. This mode is more + restrictive than SHARE mode because of only one transaction + at time can hold this lock. </para> </listitem> </varlistentry> <varlistentry> <term> - ACCESS EXCLUSIVE MODE + EXCLUSIVE MODE </term> <listitem> - <para> + + <para> + Conflicts with ROW SHARE, ROW EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, + EXCLUSIVE and ACCESS EXCLUSIVE modes. This mode is yet more + restrictive than SHARE ROW EXCLUSIVE one - it blocks concurrent + SELECT FOR UPDATE queries. </para> </listitem> </varlistentry> <varlistentry> <term> - SHARE ROW EXCLUSIVE MODE + ACCESS EXCLUSIVE MODE </term> <listitem> + <note> <para> - </para> + Automatically acquired by <command>ALTER TABLE</command>, + <command>DROP TABLE</command>, <command>VACUUM</command> statements. + </para> + </note> + + <para> + This is the most restrictive lock mode which conflicts with all other + lock modes and protects locked table from any concurrent operations. + </para> + + <note> + <para> + This lock mode is also acquired by first form of + <command>LOCK TABLE</command> (i.e. without explicit + lock mode option). + </para> + </note> </listitem> </varlistentry> + </variablelist> </para> </refsect2> @@ -151,36 +218,73 @@ LOCK [ TABLE ] <replaceable class="PARAMETER">table</replaceable> IN SHARE ROW E Description - By default, LOCK locks in exclusive mode a table inside - a transaction. Various options allow shared access, or row-level locking - control. The classic use for this is - the case where you want to select some data, then - update it inside a transaction. - If you don't explicit lock a table using LOCK statement, it will be - implicit locked only at the first - UPDATE, INSERT, - or DELETE operation. - If you don't exclusive lock the table before the select, some - other user may also read the selected data, and try and do - their own update, causing a deadlock while you both wait - for the other to release the select-induced shared lock so - you can get an exclusive lock to do the update. + Postgres always uses less restrictive + lock modes ever possible. LOCK TABLE statement + provided for cases when you might need in more restrictive locking. + + + For example, application run transaction at READ COMMITTED isolation + level and need to ensure existance data in a table for duration of + transaction. To achieve this you could use SHARE lock mode over + table before querying. This will protect data from concurrent changes + and provide your further read operations over table with data in their + real current state, because of SHARE lock mode conflicts with ROW EXCLUSIVE + one, acquired by writers, and your LOCK TABLE table IN SHARE MODE statement + will wait untill concurrent write operations (if any) commit/rollback. + (Note that to read data in their real current state running transaction + at SERIALIZABLE isolation level you have to execute LOCK TABLE + statement before execution any DML statement, when transaction defines + what concurrent changes will be visible to herself). + + - Another example of deadlock is where one user locks one - table, and another user locks a second table. While both - keep their existing locks, the first user tries to lock - the second user's table, and the second user tries to lock - the first user's table. Both users deadlock waiting for - the tables to become available. The only solution to this - is for both users to lock tables in the same order, so - user's lock acquisitions and requests to not form a deadlock. + If, in addition to requirements above, transaction is going to + change data in a table then SHARE ROW EXCLUSIVE lock mode should + be acquired to prevent deadlock conditions when two concurrent + transactions would lock table in SHARE mode and than would + try to change data in this table, both (implicitly) acquiring + ROW EXCLUSIVE lock mode that conflicts with concurrent SHARE lock. + + + Following deadlock issue (when two transaction wait one another) + touched above, you should follow two general rules to prevent + deadlock conditions: + + + + + Transactions have to acquire locks on the same objects in the same order. + + + + For example, if one application updates row R1 and than updates + row R2 (in the same transaction) then second application shouldn't + update row R2 if it's going update row R1 later (in single transaction). + Instead, it should update R1 and R2 rows in the same order as first + application. + + + + + + Transactions should acquire two conflicting lock modes only if + one of them is self-conflicting (i.e. may be held by one + transaction at time only) and should acquire most restrictive + mode first. + + + + Example for this rule is described above when told about using + SHARE ROW EXCLUSIVE mode instead of SHARE one. + + + Postgres does detect deadlocks and will - rollback transactions to resolve the deadlock. Usually, at least one - of the deadlocked transactions will complete successfully. + rollback one of waiting transactions to resolve the deadlock. @@ -195,16 +299,13 @@ LOCK [ TABLE ] table IN SHARE ROW E LOCK is a Postgres language extension. + + Except for ACCESS SHARE/EXCLUSIVE lock modes, all other + Postgres lock modes and + LOCK TABLE syntax are compatible with + Oracle ones. LOCK works only inside transactions. - - - Bug - - If the locked table is dropped then it will be automatically - unlocked even if a transaction is still in progress. - - @@ -213,18 +314,40 @@ LOCK [ TABLE ] table IN SHARE ROW E Usage + + + -- + -- SHARE lock primary key table when going to perform + -- insert into foreign key table. + -- + BEGIN WORK; + LOCK TABLE films IN SHARE MODE; + SELECT id FROM films + WHERE name = 'Star Wars: Episode I - The Phantom Menace'; + -- + -- Do ROLLBACK if record was not returned + -- + INSERT INTO films_user_comments VALUES + (_id_, 'GREAT! I was waiting it so long!'); + COMMIT WORK; + + + - --Explicit locking to prevent deadlock: + -- + -- SHARE ROW EXCLUSIVE lock primary key table when going to perform + -- delete operation. -- BEGIN WORK; - LOCK films; - SELECT * FROM films; - UPDATE films SET len = INTERVAL '100 minute' - WHERE len = INTERVAL '117 minute'; + LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE; + DELETE FROM films_user_comments WHERE id IN + (SELECT id FROM films WHERE rating < 5); + DELETE FROM films WHERE rating < 5; COMMIT WORK; + diff --git a/doc/src/sgml/ref/set.sgml b/doc/src/sgml/ref/set.sgml index e44e4c273a..3014bbda50 100644 --- a/doc/src/sgml/ref/set.sgml +++ b/doc/src/sgml/ref/set.sgml @@ -20,7 +20,7 @@ SET variable { TO | = } { 'value' | DEFAULT } SET TIME ZONE { 'timezone' | LOCAL | DEFAULT }; -SET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZED | DEFAULT } +SET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZED } @@ -350,36 +350,33 @@ SET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZED | DEFAULT } - The current transaction reads only - committed rows. READ COMMITTED is the default. + The current transaction queries read only rows committed + before a query began. READ COMMITTED is the default. - - - - - - SERIALIZABLE - - + + - The current transaction will place a - lock on every row read, so later reads in that transaction - see the rows unmodified by other transactions. + SQL92 standard requires + SERIALIZABLE to be the default isolation level. + - DEFAULT + SERIALIZABLE - Sets the isolation level for the current transaction to - . + The current transaction queries read only rows committed + before first DML statement + (SELECT/INSERT/DELETE/UPDATE/FETCH/COPY_TO) + was executed in this transaction. + @@ -789,7 +786,7 @@ SET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZED | DEFAULT } There is no SET variable - in SQL92. + in SQL92 (except for SET TRANSACTION ISOLATION LEVEL). The SQL92 syntax for SET TIME ZONE is slightly different, -- GitLab