前端之家收集整理的这篇文章主要介绍了
修改表结构DDL语句与锁,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
--当pg开启一个事务,执行dml操作时,如果另一个事务要
修改表结构,其不得不等待 --session1 中执行dml postgres=# begin; BEGIN postgres=# select pg_backend_pid(); pg_backend_pid ---------------- 4144 (1 row) postgres=# insert into t values(2,'rudy2'); INSERT 0 1 postgres=# --在session2 中执行ddl语句,发现其要等待 postgres=# begin; BEGIN postgres=# select pg_backend_pid(); pg_backend_pid ---------------- 3128 (1 row) postgres=# alter table t add password1 varchar(50); --在session3中可以发现session2发等待session 1 postgres=# SELECT locktype,postgres-# pg_locks.pid,postgres-# virtualtransaction,postgres-# transactionid,postgres-# nspname,postgres-# relname,postgres-# mode,postgres-# granted,postgres-# CASE postgres-# WHEN granted='f' THEN postgres-# 'get_lock' postgres-# WHEN granted='t' THEN postgres-# 'wait_lock' postgres-# END lock_satus,postgres-# CASE postgres-# WHEN waiting='f' THEN postgres-# 'waiting' postgres-# WHEN waiting='t' THEN postgres-# 'executing' postgres-# END lock_satus,cast(date_trunc('second',query_start) AS timestamp) AS query_start,substr(query,1,25) AS query postgres-# FROM pg_locks LEFT OUTER postgres-# JOIN pg_class postgres-# ON (pg_locks.relation = pg_class.oid) LEFT OUTER postgres-# JOIN pg_namespace postgres-# ON (pg_namespace.oid = pg_class.relnamespace),pg_stat_activity postgres-# WHERE NOT pg_locks.pid=pg_backend_pid() postgres-# AND pg_locks.pid=pg_stat_activity.pid postgres-# AND transactionid is NOT null postgres-# ORDER BY query_start; locktype | pid | virtualtransaction | transactionid | nspname | relname | mode | granted | lock_satus | lock_satus | query_start | query ---------------+------+--------------------+---------------+---------+---------+---------------+---------+------------+------------+---------------------+--------------------------- transactionid | 4144 | 8/3137 | 4638456 | | | ExclusiveLock | t | wait_lock | waiting | 2015-10-21 20:29:58 | insert into t values(2,'r' transactionid | 3128 | 2/14315 | 4638461 | | | ExclusiveLock | t | wait_lock | executing | 2015-10-21 20:30:32 | alter table t add passwor --在
修改表结构时,如果把ddl放在一个事务中,如果事务没有提交,则其它的事务必须等待,
包括查询 --在session2事务中执行一个ddl postgres=# begin; BEGIN postgres=# select pg_backend_pid(); pg_backend_pid ---------------- 3128 (1 row) postgres=# alter table t add password2 varchar(50); ALTER TABLE --在session1事务中执行dml发生等待 postgres=# begin; BEGIN postgres=# insert into t values(2,'rudy2'); --在session3中可以发现session1在等待session2 locktype | pid | virtualtransaction | transactionid | nspname | relname | mode | granted | lock_satus | lock_satus | query_start | query ---------------+------+--------------------+---------------+---------+---------+---------------+---------+------------+------------+---------------------+--------------------------- transactionid | 3128 | 2/14316 | 4638466 | | | ExclusiveLock | t | wait_lock | waiting | 2015-10-21 20:37:38 | alter table t add passwor --在session4中的
查询也发生了等待 postgres=# select * from t limit 1; --故最好不要把ddl语句放在一个事务中,如果该事务没有提交,否则其会造成后续的
查询与
修改都等待 --如果一个session中有一个大的
查询在执行,此时最好不要在另一个session中
修改表结构,因为
查询会阻塞ddl语句 --在session1中执行一个大的
查询 postgres=# select count(*) from t,t t1; --在session2中的ddl语句不得不等待 postgres=# alter table t add password3 varchar(50); --在session3中可以查看到等待的锁 locktype | pid | virtualtransaction | transactionid | nspname | relname | mode | granted | lock_satus | lock_satus | query_start | query ---------------+------+--------------------+---------------+---------+---------+---------------+---------+------------+------------+---------------------+--------------------------- transactionid | 3128 | 2/14317 | 4638470 | | | ExclusiveLock | t | wait_lock | executing | 2015-10-21 20:46:09 | alter table t add passwor --此时如果有其它session的dml操作,又不得不等待session2的ddl语句执行结束,也不得不等待,进而造成排对等待 --由此展开,在主从复制过程中,如果从库再进行类似报表的
查询,主库有一个
修改表结构的动作,wal日志复制到从库,但其却不得不等待从库
查询语句执行完成,才能应用日志,进而造成主从之间的延迟 --故最好在
修改表结构时观察下是否有大的
查询在发生