查询连接 SELECT * FROM pg_stat_activity
(1)psql -U postgres -d xx库 直接创建一个连接,状态是idle
敲begin;回车,状态变为idle in transaction
(2)程序里,
@RequestMapping(value = "/testIdle") public String testIdle() throws SQLException {
DataSource dataSource = dataSourceService.getDataSource(); PlatformTransactionManager tm = null; TransactionStatus ts = null;
Connection conn = null; PreparedStatement stm = null; ResultSet rs = null; System.out.println("to begin ..");
tm = dataSourceService.getTransactionManager(); ts = tm.getTransaction(new DefaultTransactionDefinition());
System.out.println("to update .."); String sql = "update aaaa set name='2222' where id=99999"; conn = DataSourceUtils.getConnection(dataSource); stm = conn.prepareStatement(sql); int count = stm.executeUpdate(); System.out.println(count); System.out.println("to sleep .."); try { Thread.sleep(30000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("exit,no commit .."); return "OK"; }
ts = tm.getTransaction(new DefaultTransactionDefinition()); 就获取了连接,状态是idle。 执行update时,才变成idle in transaction
(3)如果开了事务,但是没有closeConn,那么连接不会归还给连接池。 没有commit或rollback,那么该连接一直持有相关的锁,不会释放
(4)查询死锁sql,可以查出哪个连接在等锁,哪个连接拥有锁 锁等待(旧版本DB): select w1.pid as waiting_pid, w2.usename as waiting_user, w2.current_query as waiting_statement, b1.pid as blocking_pid, b2.usename as blocking_user, b2.current_query as blocking_statement from pg_locks w1 join pg_stat_activity w2 on w1.pid=w2.procpid join pg_locks b1 on w1.transactionid=b1.transactionid and w1.pid!=b1.pid join pg_stat_activity b2 on b1.pid=b2.procpid where not w1.granted;
锁等待(新版本DB): select w1.pid as waiting_pid, w2.usename as waiting_user, w2.query as waiting_statement, b1.pid as blocking_pid, b2.usename as blocking_user, b2.query as blocking_statement from pg_locks w1 join pg_stat_activity w2 on w1.pid=w2.pid join pg_locks b1 on w1.transactionid=b1.transactionid and w1.pid!=b1.pid join pg_stat_activity b2 on b1.pid=b2.pid where not w1.granted;
(5)一个连接拥有哪些锁,可以查询 select * from pg_locks A left join pg_class B on B.oid = A.relation pg_locks的pid就是pg_stat_activity的pid,或procpid(旧版本),可以根据pid过滤
(6)pg_locks里granted是true的,就是拥有的锁,false就是没有的,需要等待的锁。 virtualxid是虚拟id,不用看 transactionid是真的事务id,granted是true,就是它自己的事务id。false的话,就是它在等的事务的id。
(7)结合pg_stat_activity和pg_locks,基本可以找到哪个连接是根源。 但是,pg_stat_activity的query是当前执行的sql,这个事务执行过哪些sql是没有的。 那么,需要开db的日志。把postgresql的配置文件里,log级别改成all,还有什么deadlock都开。
(8)不要只查waiting的连接。 我这个例子,就是有idle in transaction的连接持有锁,没有释放,锁住了后来的请求。 后来的都是wait,光杀他们没有用。
|