PostgreSQL/PPAS 一例死锁问题分析

PostgreSQL 死锁问题

本文分析在 PostgreSQL 发生的一例死锁问题

执行SQL 序列

  1. 表结构和数据
    create table a(id int, value int);
    insert into a values(1,1);
    insert into a values(2,2);
  1. 事物隔离级别:读已提交
  2. 死锁发生的序列
#会话 1 开启一个事物
begin;

#会话 1 修改一行数据。修改成功,当前事物并未提交
update a set value = 3 where id = 1;

#会话 2 开启一个事物
begin;

#会话 2 修改一行数据。修改成功,当前事物并未提交
update a set value = 4 where id = 2;

# 会话 2 修改第二行数据
update a set value = 5 where id = 1;
# 由于这一行数据被会话 1 修改,且会话 1 所在事物状态未知
# 会话 2 挂起,等待会话 1 所在事物提交或回滚
# PostgreSQL 基于 MVCC 机制
# 如果会话 1 回滚,则该语句会在老数据(1)上修改;
# 如果会话 1 提交,则该语句会在新数据(3)上修改。

# 会话 1 修改第二行数据
update a set value = 6 where id = 2;
# 由于这一行数据被会话 2 修改,且会话 2 所在事物没有提交
# 会话 2 所在事物在等会话 1 的状态的确定,发生死锁
# PostgreSQL 死锁检测检测到死锁,介入处理,会话 1 所在事物被强制回滚
ERROR:  deadlock detected
DETAIL:  Process 24284 waits for ShareLock on transaction 2001; blocked by process 22401.
Process 22401 waits for ShareLock on transaction 2000; blocked by process 24284.
HINT:  See server log for query details.

# 此时会话 2 检测到会话 1 所在事物已回滚,则数据修改找到老版本的数据修改,update 语句执行完成。
postgres=# update a set value = 5 where id = 1;
UPDATE 1

问题分析

该问题是典型的 PostgreSQL 死锁问题

  1. 问题的原因是数据库会话间对数据库对象的循环上锁在成的
  2. PostgreSQL 的自动死锁检测机制能发现这类循环锁定,解决方法是一旦发生可能的死锁,就强制回滚可能造成死锁的会话的事物
  3. 用户在开发应用的过程中需要在特别注意上锁的顺序,否则在并发修改数据时容易造成死锁,导致性能低下
  4. 上述用例,如果所有回话加锁的顺序都是从小的 ID 到大的 ID,则不会发生死锁
  5. 同时,也可以使用意向锁来提前锁定需要修改的数据

相关资料

  1. Deadlocks
  2. select for update
时间: 2024-10-01 15:00:46

PostgreSQL/PPAS 一例死锁问题分析的相关文章

MySQL: 并发replace into的死锁问题分析

测试版本:MySQL5.6.23测试表: create table t1 (a int auto_increment primary key, b int, c int, unique key (b));并发执行SQL: replace into t1(b,c) values (2,3)  //使用脚本,超过3个会话 背景 replace 操作可以算是比较常用的操作类型之一,我们先来理一下,对于上例,一条简单的replace into操作的主要流程包括哪些.   Step 1. 正常的插入逻辑

MySQL加锁及死锁处理分析

<MySQL加锁处理分析> 背景 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到 MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备就MySQL/InnoDB的加锁问题,展开较为深入的分析与讨论,主要是介绍一种思路,运用此思路,拿到任何一条SQL语句,都能完整的分析出这条语句会加什么锁?会有什么样的使用风险?甚至是分析线上的一个死锁场景,了解死锁产生的原因. 注:MySQL是一个支持插件式存储引擎

谍影追踪:全球首例UEFI_BIOS木马分析

本文讲的是谍影追踪:全球首例UEFI_BIOS木马分析, 0x00简介 不久前,广州网友李先生向360安全中心求助,反映他的电脑系统自动创建名为aaaabbbb的陌生账号,杀毒软件反复报毒,即使重装系统仍然无法清除病毒.  经过360工程师远程协助的初步判断,李先生电脑主板BIOS很可能感染了恶意代码.为此,我们请李先生把主板邮寄到360公司北京总部进行分析,发现这是一种前所未见的新型BIOS BOOTKIT.由于它会在系统中设置间谍账号进行远程控制,我们将其命名为谍影木马. 与以往的BIOS恶

PostgreSQL 并行计算tpc-h测试和优化分析

PostgreSQL 并行计算tpc-h测试和优化分析 作者 digoal 日期 2016-11-08 标签 PostgreSQL , 并行计算 , TPC-H 背景 PostgreSQL 9.6首次推出支持聚合.全表扫描.HASH JOIN.nestloop的并行计算. https://www.postgresql.org/docs/9.6/static/release-9-6.html Parallel queries (Robert Haas, Amit Kapila, David Row

PostgreSQL 同步流复制锁瓶颈分析

PostgreSQL 同步流复制锁瓶颈分析 作者 digoal 日期 2016-11-07 标签 PostgreSQL , 同步流复制 , mutex , Linux , latch 背景 PostgreSQL的同步流复制实际上是通过walsender接收到的walreceiver的LSN位点,来唤醒和释放那些需要等待WAL已被备库接收的事务的. 对同步事务来说,用户发起结束事务的请求后,产生的RECORD LSN必须要小于或等于walsender接收到的walreceiver反馈的LSN位点.

SQL Server 死锁案例分析

概述 当两个或者多个进程相互阻塞时,形成一个复杂的阻塞链,参与的进程都在等待其他进程放弃其获取到的锁,没有系统的干预,无法解开这个阻塞链,这种情况就是死锁. 有些死锁是意料之内的,可以说是故意为之的. 例如,为了一致性,使用死锁来防止丢失更新. 有一些死锁是意料之外的,由于缺少索引或者事务运行时间较长导致,我们遇到的大部分都是意料之外的死锁.  SQL Server内部有个死锁的检测机制,当发生死锁时,SQL Server根据会话优先级以及工作量进行评估, 选择终止其中一个事务,解开死锁,并且向

MySQL死锁问题分析及解决方法实例详解_Mysql

MySQL死锁问题是很多程序员在项目开发中常遇到的问题,现就MySQL死锁及解决方法详解如下: 1.MySQL常用存储引擎的锁机制 MyISAM和MEMORY采用表级锁(table-level locking) BDB采用页面锁(page-level locking)或表级锁,默认为页面锁 InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁 2.各种锁特点 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低 行级锁:开销大,加锁慢;

MySQL数据库的一次死锁实例分析_Mysql

1.故事起因于2016年11月15日的一个生产bug.业务场景是:归档一个表里边的数据到历史表里边,同是删除主表记录. 2.背景场景简化如下(数据库引擎InnoDb,数据隔离级别RR[REPEATABLE]) -- 创建表test1 CREATE TABLE test1 ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(10) NOT NULL, PRIMARY KEY (id) ); insert into test1 values('hel

mysql死锁问题分析

线上某服务时不时报出如下异常(大约一天二十多次):"Deadlock found when trying to get lock;".       Oh, My God! 是死锁问题.尽管报错不多,对性能目前看来也无太大影响,但还是需要解决,保不齐哪天成为性能瓶颈.      为了更系统的分析问题,本文将从死锁检测.索引隔离级别与锁的关系.死锁成因.问题定位这五个方面来展开讨论.  图1 应用日志 1 死锁是怎么被发现的? 1.1 死锁成因&&检测方法      左图那