
想学会更多实用技巧,欢迎加入青学会MOP技术社区(实名社区)。
加入方法:公众号后台回复关键字“加入”获取小助手微信,添加后登记入会。

同时欢迎大家在评论区留言互动交流!社区会不定期举行相关的抽奖、公开分享活动。
如果你有想了解的知识点希望我们发文可以后台私信。
最近联合几个 Oracle ACE技术专家 开通了一个付费微信群,都是具有10多年金融、医疗、制造业10年以上的一线专家,坑位费399/人,无限期,目前群内近150人。加群后会有一些福利(分享各类技术文档,干货资源,问题解答等等),更有特邀嘉宾会定期在群内直播,解读AWR,快问快答等!有问题我们尽量都解答,毕竟399不能都解决所有问题。有兴趣联系微:ywu0613
内部知识库正在筹建中,不止有oracle!

正文开始
在数据库的世界里,PostgreSQL 就像一个庞大而有序的城市,事务则是这个城市中的一辆辆汽车,而 ACID 特性就是保障这些汽车安全、有序行驶的交通规则。今天,我们就来一起了解一下 PostgreSQL 事务以及它在并发情况下的那些事儿。

事务的介绍
什么是事务?
想象一下,你在网上购物,从添加商品到购物车、填写收货地址、选择支付方式,再到最后点击 “确认支付”,这一系列操作就像是一个事务。要么全部成功,你顺利买到商品;要么中间任何一个环节出错,比如支付失败,整个购物过程就相当于没有发生,你的购物车还是原来的样子,这就是数据库事务的基本概念。它是一组操作的集合,这些操作要么全部执行成功,要么全部不执行,不会出现只执行了一部分的情况。
事务的四大特性(ACID)
原子性(Atomicity) :事务是一个不可分割的整体。就好比你搭积木,要么把所有积木都成功搭上去,搭建出一个完整的造型;要么中间积木倒了,就全部恢复到最初的状态,不会出现只搭了一部分的情况。如果事务在执行过程中出错,数据库会自动回滚到事务开始之前的状态,就好像什么都没发生过一样。 一致性(Consistency) :事务执行前后,数据库的数据状态必须保持一致。举个例子,银行转账,A 账户转 1000 元给 B 账户,转账前 A 账户有 5000 元,B 账户有 3000 元,总金额是 8000 元。转账完成后,A 账户有 4000 元,B 账户有 4000 元,总金额还是 8000 元,数据库的完整性约束没有被破坏,这就是一致性。 隔离性(Isolation) :不同的事务之间彼此互不干扰。就像你在银行的 ATM 机上取钱,同时别人也在旁边的 ATM 机上存钱,你们的操作是相互独立的,不会互相影响。一个事务在操作数据时,其他事务不能干扰它,直到它完成操作。 持久性(Durability) :事务完成后,对数据库的修改是永久保存的。就像你在纸上写下的字,除非你用橡皮擦掉,否则它会一直留在那里。事务一旦提交,即使数据库发生故障,比如突然断电,之前对数据的更新也不会丢失。
事务在并发时会出现的问题
在数据库的实际应用中,很多时候会有多个事务同时进行,这就像是城市里的多条道路同时有车辆行驶,如果没有良好的交通规则,就会出现各种问题。
更新丢失
假设有一个商品库存数量是 10 件,事务 A 和事务 B 同时读取这个库存数量。事务 A 决定将库存减少 2 件,事务 B 决定将库存增加 3 件。如果事务 A 先提交,库存应该是 8 件;但如果事务 B 先提交,库存就变成了 11 件,事务 A 的操作就被 “丢失” 了。这就像是两个人同时修改同一个文档,一个人的修改覆盖了另一个人的修改。
解决办法 :对数据行加锁,只允许一个事务在某个时间段内对某一行数据进行修改,这样就能避免更新丢失的情况。
脏读
比如,事务 A 修改了一条数据,但还没有提交。事务 B 此时读取了这条被修改的数据,然后事务 A 发现修改有误,回滚了操作。这样事务 B 读取到的数据就是 “脏数据”,因为它读到的数据并不是最终确认的数据。就像你在看一本书,作者正在修改书中的内容,你看到了修改后的部分,但作者最后又改回去了,你看到的内容就是不准确的。
不可重复读
事务 A 在读取一条数据后,事务 B 修改了这条数据并提交。当事务 A 再次读取同一条数据时,得到的结果和第一次读取的不同。例如,事务 A 先查询到某员工的工资是 5000 元,事务 B 将该员工的工资修改为 6000 元并提交,事务 A 再次查询时,工资就变成了 6000 元。这就像是你在一个图书馆里,第一次借了一本书,书中的某个知识点是这样的,你还回去后,别人修改了这个知识点,你再去借来看,发现内容不一样了。
解决办法 :如果只有在修改事务完全提交之后才可以读取数据,就可以避免不可重复读的问题。
幻读
事务 A 对一批数据进行了修改,但还没有提交。事务 B 在这段时间内插入了一些新的数据,当事务 A 提交后,事务 A 再次查询时,发现多了一些之前没有的数据,就像是出现了 “幻觉”。例如,事务 A 要将所有学生的成绩从具体分数改为等级,当事务 A 改了一部分学生的成绩后,事务 B 插入了一些新的学生成绩记录,事务 A 改完后发现还有新的记录没有改过来。
解决办法 :解决幻读问题需要锁表,确保在事务执行过程中,其他事务不能插入新的数据。
事务的四个隔离级别
为了应对并发事务可能出现的问题,数据库提供了不同的事务隔离级别,就像是不同级别的交通管制措施。
读未提交(Read Uncommitted) :这是最低的隔离级别,一个事务可以读取到其他事务未提交的数据。在这个级别下,所有的并发事务问题都可能会发生,就像没有任何交通规则约束的马路,很容易出现交通事故。不过,它解决了更新丢失的问题,因为即使有多个事务同时更新同一数据,最终提交的那个事务的结果会保留下来。 读已提交(Read Committed) :只有在事务提交后,其更新结果才会被其他事务看见。这个级别解决了更新丢失和脏读的问题,就像有了基本的交通信号灯,车辆按照信号灯行驶,不会出现闯红灯的情况。大多数数据库的默认隔离级别都是读已提交,比如 Oracle、PostgreSQL 等。 可重复读(Repeated Read) :在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。这个级别解决了更新丢失、脏读和不可重复读的问题,就像是有专门的交通协管员,确保你在同一个路口看到的交通情况是一样的。少数数据库默认的隔离级别为可重复读,比如 MySQL。 串行化(Serialization) :事务串行化执行,隔离级别最高,牺牲了系统的并发性。在这个级别下,事务就像是一辆车一辆车依次通过路口,虽然不会出现任何问题,但效率较低。它可以解决并发事务的所有问题。
查看和设置事务隔离级别
查看默认的事务隔离级别 :在 PostgreSQL 中,可以通过命令 show default_transaction_isolation;
来查看默认的事务隔离级别。查看当前事务的隔离级别 :使用命令 show transaction_isolation;
可以查看当前事务的隔离级别。配置默认的隔离级别 :如果需要修改默认的事务隔离级别,可以编辑 PostgreSQL 的配置文件 postgresql.conf
,找到default_transaction_isolation
参数,将其设置为相应的隔离级别,例如'read committed'
。动态修改默认隔离级别 :也可以使用命令 set default_transaction_isolation='repeatable read';
或set default_transaction_isolation='read committed';
来动态修改默认隔离级别。动态修改当前事务的隔离级别 :使用命令 set transaction_isolation = 'repeatable read';
或set transaction isolation level repeatable read;
可以动态修改当前事务的隔离级别。
事务在 PostgreSQL 数据库中起着至关重要的作用,它就像数据库世界的 “交通规则”,确保数据的完整性和一致性。通过了解事务的特性、并发问题以及隔离级别,我们可以更好地使用 PostgreSQL 数据库,让数据的存储和操作更加安全、可靠。
往期文章回顾
MOP社区新闻
金仓专栏
告别繁琐!KingbaseES v9数据库一键安装-青学会&金仓专栏(1)
KingbaseES v9数据库Docker安装-青学会&金仓专栏(2)
DBA实战小技巧
实战:记一次RAC故障排查
DBA实战运维小技巧安装篇(一)Oracle 主流版本不同架构下的静默安装指南
DBA实战运维小技巧存储篇(一)根目录满了如何处理
DBA实战运维小技巧存储篇(二)打包迁移单机数据库至新存储
MOP社区投稿-内核开发
简单解析 IvorySQL 增强 Oracle xml 兼容能力的原理
简单讨论 PostgreSQL C语言拓展函数返回数据表的方式
简单分析 pg_config 程序的作用与原理
Redis 日志机制简介(一):SlowLog
Redis 日志机制简介(二):AOF 日志
Redis 日志机制简介(三):RDB 日志
pg_cron插件使用介绍
Redis 的指令表实现机制简介
pg几款源码工具介绍
Redis 事务功能简介




