修改表结构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日志复制到从库,但其却不得不等待从库查询语句执行完成,才能应用日志,进而造成主从之间的延迟


--故最好在修改表结构时观察下是否有大的查询在发生
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值