mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-28 07:21:51 +02:00
1b8a219eef
starting a new hashtable search no longer clobbers any other search active anywhere in the system. Fix RelationCacheInvalidate() so that it will not crash or go into an infinite loop if invoked recursively, as for example by a second SI Reset message arriving while we are still processing a prior one. |
||
---|---|---|
.. | ||
lmgr.c | ||
lock.c | ||
Makefile | ||
proc.c | ||
README |
$Header: /cvsroot/pgsql/src/backend/storage/lmgr/README,v 1.4 2000/12/22 00:51:54 tgl Exp $ There are two fundamental lock structures: the per-lockable-object LOCK struct, and the per-lock-holder HOLDER struct. A LOCK object exists for each lockable object that currently has locks held or requested on it. A HOLDER struct exists for each transaction that is holding or requesting lock(s) on each LOCK object. Lock methods describe the overall locking behavior. Currently there are two lock methods: DEFAULT and USER. (USER locks are non-blocking.) Lock modes describe the type of the lock (read/write or shared/exclusive). See src/tools/backend/index.html and src/include/storage/lock.h for more details. --------------------------------------------------------------------------- The lock manager's LOCK: tag - The key fields that are used for hashing locks in the shared memory lock hash table. This is declared as a separate struct to ensure that we always zero out the correct number of bytes. It is critical that any alignment-padding bytes the compiler might insert in the struct be zeroed out, else the hash computation will be random. tag.relId - Uniquely identifies the relation that the lock corresponds to. tag.dbId - Uniquely identifies the database in which the relation lives. If this is a shared system relation (e.g. pg_user) the dbId should be set to 0. tag.tupleId - Uniquely identifies the block/page within the relation and the tuple within the block. If we are setting a table level lock both the blockId and tupleId (in an item pointer this is called the position) are set to invalid, if it is a page level lock the blockId is valid, while the tupleId is still invalid. Finally if this is a tuple level lock (we currently never do this) then both the blockId and tupleId are set to valid specifications. This is how we get the appearance of a multi-level lock table while using only a single table (see Gray's paper on 2 phase locking if you are puzzled about how multi-level lock tables work). mask - This field indicates what types of locks are currently held on the given lockable object. It is used (against the lock table's conflict table) to determine if the new lock request will conflict with existing lock types held. Conficts are determined by bitwise AND operations between the mask and the conflict table entry for the given lock type to be set. The current representation is that each bit (1 through 5) is set when that lock type (WRITE, READ, WRITE INTENT, READ INTENT, EXTEND) has been acquired for the lock. waitProcs - This is a shared memory queue of all process structures corresponding to a backend that is waiting (sleeping) until another backend releases this lock. The process structure holds the information needed to determine if it should be woken up when this lock is released. If, for example, we are releasing a read lock and the process is sleeping trying to acquire a read lock then there is no point in waking it since the lock being released isn't what caused it to sleep in the first place. There will be more on this below (when I get to releasing locks and waking sleeping process routines). nHolding - Keeps a count of how many times this lock has been attempted to be acquired. The count includes attempts by processes which were put to sleep due to conflicts. It also counts the same backend twice if, for example, a backend process first acquires a read and then acquires a write. holders - Keeps a count of how many locks of each type have been attempted. Only elements 1 through MAX_LOCK_TYPES are used as they correspond to the lock type defined constants (WRITE through EXTEND). Summing the values of holders should come out equal to nHolding. nActive - Keeps a count of how many times this lock has been succesfully acquired. This count does not include attempts that are waiting due to conflicts, but can count the same backend twice (e.g. a read then a write -- since its the same transaction this won't cause a conflict) activeHolders - Keeps a count of how locks of each type are currently held. Once again only elements 1 through MAX_LOCK_TYPES are used (0 is not). Also, like holders, summing the values of activeHolders should total to the value of nActive. --------------------------------------------------------------------------- The lock manager's HOLDER: tag - The key fields that are used for hashing entries in the shared memory holder hash table. This is declared as a separate struct to ensure that we always zero out the correct number of bytes. tag.lock SHMEM offset of the LOCK object this holder is for. tag.pid PID of backend process that owns this holder. tag.xid XID of transaction this holder is for, or InvalidTransactionId if the holder is for session-level locking. Note that this structure will support multiple transactions running concurrently in one backend, which may be handy if we someday decide to support nested transactions. Currently, the XID field is only needed to distinguish per-transaction locks from session locks. User locks are always session locks, and we also use session locks for multi- transaction operations like VACUUM. holders - The number of successfully acquired locks of each type for this holder. (CAUTION: the semantics are not the same as the LOCK's holder[], which counts both acquired and pending requests. Probably a different name should be used...) nHolding - Sum of the holders[] array. queue - List link for shared memory queue of all the HOLDER objects for the same backend.