找回密码
 立即注册
首页 业界区 业界 PG系列:Select查询一样会被阻塞

PG系列:Select查询一样会被阻塞

苗嘉惠 昨天 22:44
我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。
在之前的理解中SELECT语句只会在对象上获取共享锁,在行上面由于MVCC机制不会申请任何锁,所以SELECT语句不会被阻塞。在PG环境中SQL语句申请的对象级别的锁类型是relation,SELECT语句仍然需要在表上面申请共享访问级别的relation锁,在遇到访问排它锁争用的情况,就会出现SELECT语句一样被阻塞,所以此时就出现了SELECT被阻塞的现象。这种现象可以非常容易的模拟出来。
模拟行级排它锁

这里通过更新同一行就可以模拟行级排它锁。
  1. 会话一:
  2. postgres_1721@postgres > update big_table set id=12313123121212312 where id=1;
  3. UPDATE 1
  4. Time: 0.788 ms
  5. 会话二:
  6. postgres_1721@postgres > update big_table set data2='1473c5de4ec1d74cce391fd78b1601fb' where id=1;
复制代码
查看锁的信息:
  1. postgres_1721@postgres > \i block.sql
  2. -[ RECORD 1 ]-+--------------------------------------------------------------------------
  3. pid           | 2399
  4. usename       | postgres
  5. datname       | postgres
  6. state         | idle in transaction
  7. wait_event    | Client: ClientRead
  8. time_state_s  | 2111
  9. time_xact_s   | 2111
  10. locked_object |
  11. locktype      |
  12. mode          |
  13. h_p_t         |
  14. w_p_t         |
  15. blocking_pids |
  16. last_session  |
  17. lock_depth    | 2399.0
  18. query         | RELEASE pg_psql_temporary_savepoint
  19. -[ RECORD 2 ]-+--------------------------------------------------------------------------
  20. pid           | 2760
  21. usename       | postgres
  22. datname       | postgres
  23. state         | active
  24. wait_event    | Lock: transactionid
  25. time_state_s  | 2250
  26. time_xact_s   | 2250
  27. locked_object | transactionid
  28. locktype      | transactionid
  29. mode          | ShareLock
  30. h_p_t         |
  31. w_p_t         | big_table:0:1
  32. blocking_pids | {2399}
  33. last_session  | 2399
  34. lock_depth    | 2399.1
  35. query         | update big_table set data2='1473c5de4ec1d74cce391fd78b1601fb' where id=1;
复制代码
这里可以看到2760会话因为transactionid锁而被阻塞。
模拟访问排它锁

在上面的情况下执行表的DDL语句即可以模拟出访问排它锁
  1. 会话三:
  2. postgres_1721@postgres > alter table big_table add column data4 text;
  3. hang住了
复制代码
查看阻塞的信息:
  1. postgres_1721@postgres > \i block.sql
  2. -[ RECORD 1 ]-+--------------------------------------------------------------------------
  3. pid           | 2399
  4. usename       | postgres
  5. datname       | postgres
  6. state         | idle in transaction
  7. wait_event    | Client: ClientRead
  8. time_state_s  | 757
  9. time_xact_s   | 757
  10. locked_object |
  11. locktype      |
  12. mode          |
  13. h_p_t         |
  14. w_p_t         |
  15. blocking_pids |
  16. last_session  |
  17. lock_depth    | 2399.0
  18. query         | RELEASE pg_psql_temporary_savepoint
  19. -[ RECORD 2 ]-+--------------------------------------------------------------------------
  20. pid           | 2760
  21. usename       | postgres
  22. datname       | postgres
  23. state         | active
  24. wait_event    | Lock: transactionid
  25. time_state_s  | 617
  26. time_xact_s   | 617
  27. locked_object | transactionid
  28. locktype      | transactionid
  29. mode          | ShareLock
  30. h_p_t         |
  31. w_p_t         | big_table:0:1
  32. blocking_pids | {2399}
  33. last_session  | 2399
  34. lock_depth    | 2399.1
  35. query         | update big_table set data2='1473c5de4ec1d74cce391fd78b1601fb' where id=1;
  36. -[ RECORD 3 ]-+--------------------------------------------------------------------------
  37. pid           | 2592
  38. usename       | postgres
  39. datname       | postgres
  40. state         | active
  41. wait_event    | Lock: relation
  42. time_state_s  | 13
  43. time_xact_s   | 2867
  44. locked_object | big_table
  45. locktype      | relation
  46. mode          | AccessExclusiveLock
  47. h_p_t         |
  48. w_p_t         |
  49. blocking_pids | {2760,2399}
  50. last_session  | 2399
  51. lock_depth    | 2760.3
  52. query         | alter table big_table add column data4 text;
复制代码
这里alter的语句申请对象的big_table的访问排它锁而被阻塞了。
SELECT语句被阻塞

任一执行一条SQL语句:
  1. 会话四:
  2. postgres_1721@postgres > \i mypid.sql
  3. pg_backend_pid
  4. ----------------
  5.            2861
  6. (1 row)
  7. Time: 0.612 ms
  8. postgres_1721@postgres > select * from big_table limit 1;
  9. hang住了。
复制代码
查询阻塞的信息:
  1. -[ RECORD 3 ]-+--------------------------------------------------------------------------
  2. pid           | 2861
  3. usename       | postgres
  4. datname       | postgres
  5. state         | active
  6. wait_event    | Lock: relation
  7. time_state_s  | 111
  8. time_xact_s   | 126
  9. locked_object | big_table
  10. locktype      | relation
  11. mode          | AccessShareLock
  12. h_p_t         |
  13. w_p_t         |
  14. blocking_pids | {2592}
  15. last_session  | 2592
  16. lock_depth    | 2592.2
  17. query         | select * from big_table limit 1;
  18. -[ RECORD 4 ]-+--------------------------------------------------------------------------
复制代码
相比之前的记录会多出上面的信息,select语句申请big_table访问共享锁时被阻塞了。
总结

通过上面的列子中其实可以看到SELECT语句一样的会被阻塞,不过在PG环境中SELECT的阻塞分析起来比Oracle还要更简单一些,因为在Oracle中元数据的锁不会出现在v$lock中而是出现在dba_kgllock中,同时event也是显示的元数据等待事件,相比PG来说这点会更直观很多。
------------------作者介绍-----------------------
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)
1.png


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册