PostgreSQL 中如何处理数据的并发更新冲突解决?

文章目录

  • 一、并发更新冲突的场景
  • 二、PostgreSQL 中的并发控制机制
    • (一) 封锁机制
    • (二) 事务隔离级别
  • 三、并发更新冲突的解决方法
    • (一) 重试机制
    • (二) 使用乐观并发控制
    • (三) 使用悲观并发控制
    • (四) 应用版本字段
    • (五) 基于时间戳的冲突解决
  • 四、实际应用中的考虑因素
    • (一) 性能影响
    • (二) 业务逻辑适应性
    • (三) 数据分布和访问模式
  • 五、示例分析

美丽的分割线

PostgreSQL


在数据库并发操作环境中,多个事务同时尝试更新相同的数据可能导致冲突。PostgreSQL 提供了一系列机制来处理这些并发更新冲突,以确保数据的一致性和完整性。

美丽的分割线

一、并发更新冲突的场景

当两个或多个事务同时尝试对同一行数据进行修改时,就可能发生并发更新冲突。常见的场景包括:

  1. 同时修改同一行的不同列
  2. 同时对同一列进行不同的值更新

美丽的分割线

二、PostgreSQL 中的并发控制机制

PostgreSQL 主要使用 MVCC(多版本并发控制,Multiversion Concurrency Control ) 来处理并发事务。MVCC 允许事务读取到符合其隔离级别需求的数据版本,而不需要加锁阻塞其他事务的读操作。然而,在写操作时,仍可能出现冲突。

(一) 封锁机制

PostgreSQL 使用多种类型的锁来控制对数据的并发访问。常见的锁类型包括:

  1. 共享锁(Shared Lock):允许其他事务也获取共享锁,但阻止获取排他锁。常用于读取操作。
  2. 排他锁(Exclusive Lock):阻止其他事务获取任何类型的锁,常用于写入操作。

锁的粒度可以是行级(Row-Level)、页级(Page-Level)和表级(Table-Level)。

(二) 事务隔离级别

PostgreSQL 支持四种事务隔离级别:

  1. 读未提交(Read Uncommitted):这是最低的隔离级别,一个事务可以读取到其他事务未提交的数据修改,可能导致脏读、不可重复读和幻读等问题。
  2. 读已提交(Read Committed):事务只能读取已经提交的数据,避免了脏读,但仍可能出现不可重复读和幻读。
  3. 可重复读(Repeatable Read):在一个事务内多次读取相同的数据会得到相同的结果,避免了不可重复读,但可能出现幻读。
  4. 串行化(Serializable):最高的隔离级别,通过严格的并发控制确保事务的串行执行,避免了脏读、不可重复读和幻读。

美丽的分割线

三、并发更新冲突的解决方法

(一) 重试机制

一种简单的方法是当冲突发生时,让事务进行重试。示例如下:

DO
$$
DECLARE
    conflict_detected BOOLEAN := FALSE;
BEGIN
    LOOP
        -- 尝试执行更新操作
        UPDATE products SET price = 100 WHERE id = 1;

        -- 检查是否有冲突(例如,通过检查受影响的行数)
        IF NOT FOUND THEN
            conflict_detected := TRUE;
        ELSE
            EXIT;
        END IF;

        -- 若有冲突,等待一段时间并重试
        IF conflict_detected THEN
            PERFORM pg_sleep(1);
        END IF;
    END LOOP;
END;
$$;

在上述示例中,如果更新操作没有影响到任何行(表示可能存在冲突),则设置一个标志,等待一段时间后重试。

(二) 使用乐观并发控制

乐观并发控制假设并发冲突很少发生。在这种方式中,事务在更新数据时不进行加锁,而是在提交时检查数据是否被其他事务修改。如果没有冲突,事务成功提交;如果有冲突,事务回滚并根据需要重试。

-- 获取数据的初始版本
SELECT price AS original_price FROM products WHERE id = 1;

-- 进行业务处理和修改
UPDATE products SET price = 100 WHERE id = 1 AND price = original_price;

在上述示例中,更新操作仅在数据未被其他事务修改的情况下成功。

(三) 使用悲观并发控制

悲观并发控制则假设并发冲突很可能发生,在事务执行期间获取所需的锁来阻塞其他可能冲突的事务。

BEGIN;

-- 获取排他锁
LOCK TABLE products IN SHARE ROW EXCLUSIVE MODE;

-- 进行数据更新
UPDATE products SET price = 100 WHERE id = 1;

COMMIT;

(四) 应用版本字段

给表添加一个版本字段来跟踪数据的更改。

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    price DECIMAL(10, 2),
    version INT DEFAULT 0
);

在更新数据时,同时递增版本字段:

UPDATE products SET price = 100, version = version + 1 WHERE id = 1 AND version = <expected_version>;

如果更新影响的行数为 0,表示存在冲突,因为预期的版本与实际的版本不一致。

(五) 基于时间戳的冲突解决

为每行数据添加一个时间戳字段,记录数据的最后修改时间。

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    price DECIMAL(10, 2),
    last_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

在更新时,仅更新时间戳比当前事务读取的时间戳更早的数据:

UPDATE products SET price = 100 WHERE id = 1 AND last_modified <= <read_timestamp>;

美丽的分割线

四、实际应用中的考虑因素

(一) 性能影响

  1. 不同的冲突解决方法对数据库性能有不同的影响。例如,使用封锁可能导致其他事务的等待,增加系统的阻塞时间,从而影响并发性。而乐观并发控制在冲突很少发生时性能较好,但在冲突频繁时可能导致大量的事务重试,增加了总体的执行时间。
  2. 应用版本字段或基于时间戳的方法可能需要额外的存储空间来维护版本或时间戳信息,并在更新时进行额外的判断和处理。

(二) 业务逻辑适应性

  1. 某些业务场景可能更适合某种特定的冲突解决方法。例如,如果业务对数据的一致性要求非常高,不能容忍任何不一致的情况,那么悲观并发控制或串行化隔离级别可能是更好的选择。
  2. 对于冲突不太频繁且对响应时间要求较高的场景,乐观并发控制可能更合适。

(三) 数据分布和访问模式

  1. 如果数据的访问是高度并发的,并且多个事务经常同时访问相同的数据行,那么需要更加谨慎地选择冲突解决方法,以避免过度的阻塞和冲突。
  2. 对于数据分布较为均匀,冲突概率较低的情况,可以采用相对简单和高效的方法,如乐观并发控制。

美丽的分割线

五、示例分析

假设我们有一个在线商店的库存管理系统,其中有一个 inventory 表来存储商品的库存数量。

CREATE TABLE inventory (
    product_id INT PRIMARY KEY,
    quantity INT,
    last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

现在有两个并发的事务:

事务 1:

BEGIN;
SELECT * FROM inventory WHERE product_id = 1;
-- 假设读取到的数量为 10
UPDATE inventory SET quantity = 5 WHERE product_id = 1 AND last_updated <= <read_timestamp>;
COMMIT;

事务 2:

BEGIN;
SELECT * FROM inventory WHERE product_id = 1;
-- 假设也读取到的数量为 10
UPDATE inventory SET quantity = 8 WHERE product_id = 1 AND last_updated <= <read_timestamp>;
COMMIT;

如果这两个事务几乎同时执行,可能会发生冲突。

如果我们采用基于时间戳的冲突解决方法:

  1. 事务 1 读取数据时获取了当前的时间戳(T1)。
  2. 事务 2 读取数据时获取了稍晚的时间戳(T2)。

当事务 1 尝试更新时,如果自它读取以来没有其他事务修改数据(即 last_updated <= T1),则更新成功。

当事务 2 尝试更新时,如果发现数据的 last_updated 大于 T2(说明在事务 2 读取之后被修改过),则更新失败,事务 2 可以选择回滚并重试,或者根据业务逻辑进行其他处理。


美丽的分割线

🎉相关推荐

  • 🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
  • 📚领书:PostgreSQL 入门到精通.pdf
  • 📙PostgreSQL 中文手册
  • 📘PostgreSQL 技术专栏

PostgreSQL

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/789372.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用机器学习 最近邻算法(Nearest Neighbors)进行点云分析

使用 NearestNeighbors 进行点云分析 在数据分析和机器学习领域&#xff0c;最近邻算法&#xff08;Nearest Neighbors&#xff09;是一种常用的非参数方法。它广泛应用于分类、回归和聚类分析等任务。下面将介绍如何使用 scikit-learn 库中的 NearestNeighbors 类来进行点云数…

打开excel时弹出stdole32.tlb

问题描述 打开excel时弹出stdole32.tlb 如下图&#xff1a; 解决方法 打开 Microsoft Excel 并收到关于 stdole32.tlb 的错误提示时&#xff0c;通常意味着与 Excel 相关的某个组件或类型库可能已损坏或不兼容。 stdole32.tlb 是一个用于存储自动化对象定义的类型库&#x…

【解读大模型(LLM)的token】

文末有福利&#xff01; 当人们谈论大型语言模型的大小时&#xff0c;参数会让我们了解神经网络的结构有多复杂&#xff0c;而token的大小会让我们知道有多少数据用于训练参数。 正像陆奇博士所说的那样&#xff0c;大型语言模型为从文本生成到问题回答的各种任务提供了令人印象…

2024年的设计理念革新:快速获取设计趋势的资源集合!

随着2024年第三季度开始&#xff0c;今年的设计趋势也逐渐出现。与2023 年设计相比&#xff0c;趋势变化空间不大&#xff0c;大部分是在 2023 年度设计趋势的延伸和发展。即使趋势不会一直改变&#xff0c;了解趋势对设计师来说仍然非常重要。接下来&#xff0c;本文将与你分享…

拥抱应用创新,拒绝无谓的模型竞争

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

如何查询并下载韩国签证

登录大韩民国签证门户网站&#xff08;https://www.visa.go.kr&#xff09;&#xff0c;点击“查询/签发”- “办理进度查询及打印”。 2) 输入护照号码、英文姓名及出生日期后点击查询。 3) 若签证通过&#xff0c;办理状态信息栏下面会显示签证信息。 4&#xff09;点击“签证…

大数据信用评分太低,是什么原因引起的?

在大数据时代&#xff0c;个人的大数据信用评分变得尤为重要。它不仅影响着我们能否顺利地获得贷款、信用卡等金融服务&#xff0c;还在很多方面影响着我们的日常生活。那么&#xff0c;哪些原因可能会导致我们的大数据信用评分降低呢?本文将对此进行详细的总结&#xff0c;一…

防火墙安全策略用户认证综合实验

实验拓扑&#xff1a; 实验要求&#xff1a; 1&#xff1a;DMz区内的服务器&#xff0c;办公区仅能在办公时间内(9:00-18:00)可以访问&#xff0c;生产区的设备全天可以访问 2&#xff1a;生产区不允许访问互联网&#xff0c;办公区和游客区允许访问互联网 3&#xff1a;办公…

ARM_Linux驱动开发——字符设备驱动开发(上)

目录 一、Linux驱动开发思维 二、Linux驱动开发分类 三、“ ARM_Linux驱动开发——字符设备驱动开发 ” 字符设备驱动简介 前言 在分享Linux驱动开发之前&#xff0c;我想带大家首先回顾一下裸机驱动开发和Linux驱动开发的区别。 1、运行环境和操作系统&#xff1a; 裸机驱…

【无需公网IP】在树莓派上搭建Web站点

目录 1.概述 2.使用 Raspberry Pi Imager 安装 Raspberry Pi OS 3.设置 Apache Web 服务器 3.1测试 web 站点 3.2安装静态样例站点 3.3将web站点发布到公网 3.4安装 Cpolar 3.5cpolar进行token认证 3.6生成cpolar随机域名网址 3.7生成cpolar二级子域名 3.8将参数保存…

边框插画:成都亚恒丰创教育科技有限公司

边框插画&#xff1a;艺术与生活的精致边界 在视觉艺术的广阔天地里&#xff0c;边框插画以其独特的魅力和细腻的表达方式&#xff0c;成为连接艺术与生活的一道精致边界。成都亚恒丰创教育科技有限公司它不仅仅是图像的外框装饰&#xff0c;更是情感、故事与创意的延伸&#…

基于Matlab和Python泰勒图的绘制

一、泰勒图介绍 泰勒图:泰勒图1常用于评价模型的精度,常用的精度指标有相关系数,标准差以及均方根误差(RMSE)。一般而言,泰勒图中的散点代表模型,辐射线代表相关系数,横纵轴代表标准差,而虚线代表均方根误差。泰勒图一改以往用散点图这种只能呈现两个指标来表示模型精度…

《基于 LatentFactor + Redis + ES 实现动态药房分配方法》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;欢迎多多交流。&am…

echarts——横坐标轴文字过长如何换行

横坐标轴文字过长,想要换行 实现如下效果 具体实现代码如下&#xff1a; axisLabel: {show: true,interval: 0,formatter: function (value) {var ret "";//拼接加\n返回的类目项 var maxLength 4;//每项显示文字个数 var valLength value.length;//X轴类目项…

MP | 基于kmer的泛基因组分析方法及应用

2024年5月24日&#xff0c;中国农业大学分子设计育种前沿科学中心作物杂种优势与利用教育部重点实验室郭伟龙与姚颖垠团队在《Molecular Plant》发表了题为《A k-mer-based pangenome approach for cataloging seed-storage-protein genes in wheat to facilitate genotype-to-…

一道笔试题 - 反转列表

文章目录 描述预期结果代码 描述 给定一个单链表的头结点pHead(该头节点是有值的&#xff0c;比如在下图&#xff0c;它的val是1)&#xff0c;长度为n&#xff0c;反转该链表后&#xff0c;返回新链表的表头。 如当输入链表{1,2,3}时&#xff0c; 经反转后&#xff0c;原链表变…

【RHCE】NFS 实验

主服务器 下载nfs-utils软件包&#xff1a; 1.如果停⽌该服务&#xff0c;启动并启⽤该服务&#xff1a; systemctl enable - now rpcbind 2.要启动 NFS 服务器&#xff0c;并使其在引导时⾃动启动&#xff1a;systemctl enable - now nfs- server 3.配置防火墙&#xff0c;开…

基于swagger插件的方式推送接口文档至torna

目录 一、前言二、登录torna三、创建/选择空间四、创建/选择项目五、创建/选择应用六、获取应用的token七、服务推送7.1 引入maven依赖7.2 test下面按照如下方式新建文件 一、前言 Torna作为一款企业级文档管理系统&#xff0c;支持了很多种接口文档的推送方式。官方比较推荐的…

【深度学习】PyTorch深度学习笔记02-线性模型

1. 监督学习 2. 数据集的划分 3. 平均平方误差MSE 4. 线性模型Linear Model 用穷举法确定线性模型的参数 import numpy as np import matplotlib.pyplot as pltx_data [1.0, 2.0, 3.0] y_data [2.0, 4.0, 6.0]def forward(x):return x * w# loss function 是 均方根误差 lo…

YoloV8改进策略:卷积篇Kan行天下之JacobiKAN,KAN遇见Jacobi多项式

摘要 将Kolmogorov-Arnold Networks (KAN) 中的B-spline替换为Jacobi多项式是一个很有创意的想法,因为Jacobi多项式在函数逼近方面表现出色,并且具有递归计算的特性。经过测试,Jacobi多项式的KAN在YoloV8中,取得了非常不错的涨点效果。下面我将概述如何构建基于Jacobi多项…