[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[备忘]postgresql死锁调查

上一篇:[备忘]postgresql使用limit 1反倒慢……
下一篇:[备忘]postgresql按ctid查询数据

添加日期:2021-6-24 14:45:06 快速返回   返回列表 阅读214次

查询连接
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,光杀他们没有用。

 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved