Postgres2015全国用户大会将于11月20至21日在北京丽亭华苑酒店召开。本次大会嘉宾阵容强大,国内顶级PostgreSQL数据库专家将悉数到场,并特邀欧洲、俄罗斯、日本、美国等国家和地区的数据库方面专家助阵:
|
|
postgres=# create table t1(id int);CREATE TABLE
postgres=# begin;BEGINpostgres=# insert into t1 values (1);INSERT 0 1
postgres=# alter table t1 add column info text;waiting......
postgres=# create or replace function f_lock_level(i_mode text) returns int as $$declarebegincase i_modewhen 'INVALID' then return 0;when 'AccessShareLock' then return 1;when 'RowShareLock' then return 2;when 'RowExclusiveLock' then return 3;when 'ShareUpdateExclusiveLock' then return 4;when 'ShareLock' then return 5;when 'ShareRowExclusiveLock' then return 6;when 'ExclusiveLock' then return 7;when 'AccessExclusiveLock' then return 8;else return 0;end case;end;$$ language plpgsql strict;
postgres=# with t_wait as(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a,transactionid,b.query,b.xact_start,b.query_start,b.usename,b.datname from pg_locks a,pg_stat_activity b where a.pid=b.pid and not a.granted),t_run as(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a,transactionid,b.query,b.xact_start,b.query_start,b.usename,b.datname from pg_locks a,pg_stat_activity b where a.pid=b.pid and a.granted)select r.locktype,r.mode r_mode,r.usename r_user,r.datname r_db,r.relation::regclass,r.pid r_pid,r.page r_page,r.tuple r_tuple,r.xact_start r_xact_start,r.query_start r_query_start,now()-r.query_start r_locktime,r.query r_query,w.mode w_mode,w.pid w_pid,w.page w_page,w.tuple w_tuple,w.xact_start w_xact_start,w.query_start w_query_start,now()-w.query_start w_locktime,w.query w_queryfrom t_wait w,t_run r wherer.locktype is not distinct from w.locktype andr.database is not distinct from w.database andr.relation is not distinct from w.relation andr.page is not distinct from w.page andr.tuple is not distinct from w.tuple andr.classid is not distinct from w.classid andr.objid is not distinct from w.objid andr.objsubid is not distinct from w.objsubid andr.transactionid is not distinct from w.transactionid andr.pid <> w.pidorder by f_lock_level(w.mode)+f_lock_level(r.mode) desc,r.xact_start;
-[ RECORD 1 ]-+-------------------------------------locktype | relationr_mode | RowExclusiveLockr_user | postgresr_db | postgresrelation | t1r_pid | 16927r_page |r_tuple |r_xact_start | 2015-06-18 15:30:07.578806+08r_query_start | 2015-06-18 15:30:12.988851+08r_locktime | 00:07:22.879003r_query | insert into t1 values (1);w_mode | AccessExclusiveLockw_pid | 16881w_page |w_tuple |w_xact_start | 2015-06-18 15:30:26.749872+08w_query_start | 2015-06-18 15:30:26.749872+08w_locktime | 00:07:09.117982w_query | alter table t1 add column info text;
postgres=# insert into t1 values (1);waiting ......
-[ RECORD 1 ]-+-------------------------------------locktype | relationr_mode | RowExclusiveLockr_user | postgresr_db | postgresrelation | t1r_pid | 16927r_page |r_tuple |r_xact_start | 2015-06-18 15:30:07.578806+08r_query_start | 2015-06-18 15:30:12.988851+08r_locktime | 00:08:47.723949r_query | insert into t1 values (1);w_mode | AccessExclusiveLockw_pid | 16881w_page |w_tuple |w_xact_start | 2015-06-18 15:30:26.749872+08w_query_start | 2015-06-18 15:30:26.749872+08w_locktime | 00:08:33.962928w_query | alter table t1 add column info text;-[ RECORD 2 ]-+-------------------------------------locktype | relationr_mode | RowExclusiveLockr_user | postgresr_db | postgresrelation | t1r_pid | 16927r_page |r_tuple |r_xact_start | 2015-06-18 15:30:07.578806+08r_query_start | 2015-06-18 15:30:12.988851+08r_locktime | 00:08:47.723949r_query | insert into t1 values (1);w_mode | RowExclusiveLockw_pid | 17205w_page |w_tuple |w_xact_start | 2015-06-18 15:38:41.204786+08w_query_start | 2015-06-18 15:38:41.204786+08w_locktime | 00:00:19.508014w_query | insert into t1 values (1);
# vi src/include/pg_config_manual.h/** Enable debugging print statements for lock-related operations.*/#define LOCK_DEBUG
# gmake distclean# ./configure --prefix=/opt/pgsql9.5 --with-pgport=1922 --with-perl --with-python --with-tcl --with-openssl --with-pam --with-ldap --with-libxml --with-libxslt --enable-thread-safety --with-blocksize=32 --enable-debug# gmake && gmake install
$ vi postgresql.conftrace_locks = ontrace_userlocks = ondebug_deadlocks = on
$ pg_ctl restart -m fast
postgres=# set client_min_messages=log;postgres=# \set VERBOSITY verbose
postgres=# begin;BEGINpostgres=# alter table t1 add column c1 int;LOG: 00000: LockAcquire: lock [13181,16903] AccessExclusiveLockLOCATION: LockAcquireExtended, lock.c:724LOG: 00000: LockAcquire: new: lock(0x7f79f1a620c8) id(13181,16903,0,0,0,1) grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 wait(0) type(AccessExclusiveLock)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: LockAcquire: new: proclock(0x7f79f82739a8) lock(0x7f79f1a620c8) method(1) proc(0x7f7a0fec71b8) hold(0)LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: LockCheckConflicts: no conflict: proclock(0x7f79f82739a8) lock(0x7f79f1a620c8) method(1) proc(0x7f7a0fec71b8) hold(0)LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: GrantLock: lock(0x7f79f1a620c8) id(13181,16903,0,0,0,1) grantMask(100) req(0,0,0,0,0,0,0)=1 grant(0,0,0,0,0,0,0)=1 wait(0) type(AccessExclusiveLock)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: LockAcquire: lock [13181,16903] AccessExclusiveLockLOCATION: LockAcquireExtended, lock.c:724ALTER TABLE
postgres=# rollback;LOG: 00000: LockReleaseAll: lockmethod=1LOCATION: LockReleaseAll, lock.c:1949LOG: 00000: LockReleaseAll: proclock(0x7f79f82739a8) lock(0x7f79f1a620c8) method(1) proc(0x7f7a0fec71b8) hold(100)LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: LockReleaseAll: lock(0x7f79f1a620c8) id(13181,16903,0,0,0,1) grantMask(100) req(0,0,0,0,0,0,0)=1 grant(0,0,0,0,0,0,0)=1 wait(0) type(INVALID)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: UnGrantLock: updated: lock(0x7f79f1a620c8) id(13181,16903,0,0,0,1) grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 wait(0) type(AccessExclusiveLock)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: UnGrantLock: updated: proclock(0x7f79f82739a8) lock(0x7f79f1a620c8) method(1) proc(0x7f7a0fec71b8) hold(0)LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: LockReleaseAll: updated: lock(0x7f79f1a620c8) id(13181,16903,0,0,0,1) grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 wait(0) type(INVALID)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: CleanUpLock: deleting: proclock(0x7f79f82739a8) lock(0x7f79f1a620c8) method(1) proc(0x7f7a0fec71b8) hold(0)LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: CleanUpLock: deleting: lock(0x7f79f1a620c8) id(13181,16903,0,0,0,1) grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 wait(0) type(INVALID)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: LockReleaseAll doneLOCATION: LockReleaseAll, lock.c:2196LOG: 00000: LockReleaseAll: lockmethod=2LOCATION: LockReleaseAll, lock.c:1949LOG: 00000: LockReleaseAll doneLOCATION: LockReleaseAll, lock.c:2196ROLLBACK
postgres=# begin;BEGINpostgres=# insert into t1 values (1);INSERT 0 1
postgres=# begin;BEGINpostgres=# alter table t1 add column c1 int;LOG: 00000: LockAcquire: lock [13181,16903] AccessExclusiveLock -- 请求AEL锁LOCATION: LockAcquireExtended, lock.c:724LOG: 00000: LockAcquire: new: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(0) req(0,0,0,0,0,0,0)=0 grant(0,0,0,0,0,0,0)=0 wait(0) type(RowExclusiveLock)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: LockAcquire: new: proclock(0x7f79f8273960) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec6ed0) hold(0)LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: GrantLock: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(8) req(0,0,1,0,0,0,0)=1 grant(0,0,1,0,0,0,0)=1 wait(0) type(RowExclusiveLock)LOCATION: LOCK_PRINT, lock.c:319
LOG: 00000: LockAcquire: found: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(8) req(0,0,1,0,0,0,0)=1 grant(0,0,1,0,0,0,0)=1 wait(0) type(AccessExclusiveLock)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: LockAcquire: new: proclock(0x7f79f8273918) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec71b8) hold(0)LOCATION: PROCLOCK_PRINT, lock.c:331
LOG: 00000: LockCheckConflicts: conflicting: proclock(0x7f79f8273918) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec71b8) hold(0)LOCATION: PROCLOCK_PRINT, lock.c:331
LOG: 00000: WaitOnLock: sleeping on lock: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(8) req(0,0,1,0,0,0,0)=2 grant(0,0,1,0,0,0,0)=1 wait(0) type(AccessExclusiveLock)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: DumpAllLocks: waiting on: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(8) req(0,0,1,0,0,0,0)=2 grant(0,0,1,0,0,0,0)=1 wait(1) type(INVALID)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: DumpAllLocks: proclock(0x7f79f8273960) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec6ed0) hold(8)LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: DumpAllLocks: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(8) req(0,0,1,0,0,0,0)=2 grant(0,0,1,0,0,0,0)=1 wait(1) type(INVALID)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: DumpAllLocks: proclock(0x7f79f8273918) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec71b8) hold(0)LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: DumpAllLocks: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(8) req(0,0,1,0,0,0,0)=2 grant(0,0,1,0,0,0,0)=1 wait(1) type(INVALID)LOCATION: LOCK_PRINT, lock.c:319
postgres=# insert into t1 values (1);LOG: 00000: LockAcquire: lock [13181,16903] RowExclusiveLockLINE 1: insert into t1 values (1);^LOCATION: LockAcquireExtended, lock.c:724LOG: 00000: LockAcquire: found: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(108) req(0,0,1,0,0,0,0)=3 grant(0,0,1,0,0,0,0)=2 wait(1) type(RowExclusiveLock)LINE 1: insert into t1 values (1);^LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: LockAcquire: new: proclock(0x7f79f82737b0) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec6be8) hold(0)LINE 1: insert into t1 values (1);^LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: WaitOnLock: sleeping on lock: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(108) req(0,0,2,0,0,0,0)=4 grant(0,0,1,0,0,0,0)=2 wait(1) type(RowExclusiveLock)LINE 1: insert into t1 values (1);^LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: DumpAllLocks: waiting on: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(108) req(0,0,2,0,0,0,0)=4 grant(0,0,1,0,0,0,0)=2 wait(2) type(INVALID)LINE 1: insert into t1 values (1);^LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: DumpAllLocks: proclock(0x7f79f82737b0) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec6be8) hold(0)LINE 1: insert into t1 values (1);^LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: DumpAllLocks: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(108) req(0,0,2,0,0,0,0)=4 grant(0,0,1,0,0,0,0)=2 wait(2) type(INVALID)LINE 1: insert into t1 values (1);^LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: DumpAllLocks: proclock(0x7f79f8273960) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec6ed0) hold(108)LINE 1: insert into t1 values (1);^LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: DumpAllLocks: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(108) req(0,0,2,0,0,0,0)=4 grant(0,0,1,0,0,0,0)=2 wait(2) type(INVALID)LINE 1: insert into t1 values (1);^LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: DumpAllLocks: proclock(0x7f79f8273918) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec71b8) hold(0)LINE 1: insert into t1 values (1);^LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: DumpAllLocks: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(108) req(0,0,2,0,0,0,0)=4 grant(0,0,1,0,0,0,0)=2 wait(2) type(INVALID)LINE 1: insert into t1 values (1);^LOCATION: LOCK_PRINT, lock.c:319
postgres=# begin;BEGINpostgres=# lock table t1 in access exclusive mode nowait;LOG: 00000: LockAcquire: lock [13181,16903] AccessExclusiveLockLOCATION: LockAcquireExtended, lock.c:724LOG: 00000: LockAcquire: found: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(108) req(0,0,1,0,0,0,0)=3 grant(0,0,1,0,0,0,0)=2 wait(1) type(AccessExclusiveLock)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: LockAcquire: new: proclock(0x7f79f82737b0) lock(0x7f79f1a62020) method(1) proc(0x7f7a0fec6be8) hold(0)LOCATION: PROCLOCK_PRINT, lock.c:331LOG: 00000: LockAcquire: conditional lock failed: lock(0x7f79f1a62020) id(13181,16903,0,0,0,1) grantMask(108) req(0,0,1,0,0,0,0)=3 grant(0,0,1,0,0,0,0)=2 wait(1) type(AccessExclusiveLock)LOCATION: LOCK_PRINT, lock.c:319LOG: 00000: LockReleaseAll: lockmethod=1LOCATION: LockReleaseAll, lock.c:1949LOG: 00000: LockReleaseAll doneLOCATION: LockReleaseAll, lock.c:2196LOG: 00000: LockReleaseAll: lockmethod=2LOCATION: LockReleaseAll, lock.c:1949LOG: 00000: LockReleaseAll doneLOCATION: LockReleaseAll, lock.c:2196ERROR: 55P03: could not obtain lock on relation "t1"LOCATION: RangeVarGetRelidExtended, namespace.c:391
postgres=# set lock_timeout='1ms';SETpostgres=# alter table t1 add column cc int; -- 等待1毫秒后如果无法获得锁,立即返回。ERROR: canceling statement due to lock timeout
postgres=# \h lockCommand: LOCKDescription: lock a tableSyntax:LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
where lockmode is one of:
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE| SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE例如,postgres=# begin;BEGINpostgres=# lock table t1 in access exclusive mode nowait; -- 如果获得锁失败了,不需要执行下面的DDL。LOCK TABLEpostgres=# alter table t1 add column cc1 int;ALTER TABLEpostgres=# end;COMMIT
LockRelationOidLockRelationLockRelationIdForSessionLockRelationForExtensionXactLockTableInsertXactLockTableWaitSpeculativeInsertionLockAcquireSpeculativeInsertionWaitLockDatabaseObjectLockSharedObjectLockSharedObjectForSession
CREATE OR REPLACE FUNCTION online_ddl_command()RETURNS event_triggerLANGUAGE plpgsqlAS $$BEGINraise notice 'event trigger';perform 1 from pg_stat_activity where pid=pg_backend_pid() and waiting;if found thenRAISE EXCEPTION 'command % is waiting lock, I must abort it.', tg_tag;end if;END;$$;
CREATE EVENT TRIGGER online_ddl ON ddl_command_startEXECUTE PROCEDURE online_ddl_command();
/** LockAcquire -- Check for lock conflicts, sleep if conflict found,* set lock if/when no conflicts.** Inputs:* locktag: unique identifier for the lockable object* lockmode: lock mode to acquire* sessionLock: if true, acquire lock for session not current transaction* dontWait: if true, don't wait to acquire lock** Returns one of:* LOCKACQUIRE_NOT_AVAIL lock not available, and dontWait=true* LOCKACQUIRE_OK lock successfully acquired* LOCKACQUIRE_ALREADY_HELD incremented count for lock already held** In the normal case where dontWait=false and the caller doesn't need to* distinguish a freshly acquired lock from one already taken earlier in* this same transaction, there is no need to examine the return value.** Side Effects: The lock is acquired and recorded in lock tables.** NOTE: if we wait for the lock, there is no way to abort the wait* short of aborting the transaction.*/LockAcquireResultLockAcquire(const LOCKTAG *locktag,LOCKMODE lockmode,bool sessionLock,bool dontWait){return LockAcquireExtended(locktag, lockmode, sessionLock, dontWait, true);}