PostgreSQL 10.1 手册_部分 II. SQL 语言_第 13 章 并发控制_13.4. 应用级别的数据完整性检查

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: 13.4. 应用级别的数据完整性检查 13.4.1. 用可序列化事务来强制一致性 13.4.2. 使用显式锁定强制一致性 对于使用读已提交事务的数据完整性强制业务规则非常困难,因为对每一个语句数据视图都在变化,并且如果一个写冲突发生即使一个单一语句也不能把它自己限制到该语句的快照。

13.4. 应用级别的数据完整性检查

对于使用读已提交事务的数据完整性强制业务规则非常困难,因为对每一个语句数据视图都在变化,并且如果一个写冲突发生即使一个单一语句也不能把它自己限制到该语句的快照。

虽然一个可重复读事务在其执行期间有一个稳定的数据视图,在使用MVCC快照进行数据一致性检查时也有一个小问题,它涉及到被称为读/写冲突的东西。如果一个事务写数据并且一个并发事务尝试读相同的数据(不管是在写之前还是之后),它不能看到其他事务的工作。读取事务看起来是第一个执行的,不管哪个是第一个启动或者哪个是第一个提交。如果就到此为止,则没有问题,但是如果读取者也写入被一个并发事务读取的数据,现在有一个事务好像是已经在前面提到的任何一个事务之前运行。如果看起来最后执行的事务实际上第一个提交,在这些事务的执行顺序图中很容易出现一个环。当这样一个环出现时,完整性检查在没有任何帮助的情况下将不会正确地工作。

正如第 13.2.3 节中提到的,可序列化事务仅仅是可重复读事务增加了对读/写冲突的危险模式的非阻塞监控。当检测到一个可能导致表面的执行顺序中产生环的模式,涉及到的一个事务将被回滚来打破该环。

13.4.1. 用可序列化事务来强制一致性

如果可序列化事务隔离级别被用于所有需要一个一致数据视图的写入和读取,不需要其他的工作来保证一致性。在PostgreSQL中,来自于其他环境的被编写成使用可序列化事务来保证一致性的软件应该只工作在这一点上。

当使用这种技术时,如果应用软件通过一个框架来自动重试由于序列化错误而回滚的事务,它将避免为应用程序员带来不必要的负担。把default_transaction_isolation设置为serializable可能是个好主意。通过触发器中的事务隔离级别检查来采取某些动作来保证没有其他事务隔离级别被使用(由于疏忽或者为了破坏完整性检查)也是明智的。

性能建议见第 13.2.3 节

警告

这个级别的使用可序列化事务的完整性保护还没有扩展到热备份模式(第 26.5 节)。由于这个原因,那些使用热备份的系统可能想要在主控机上使用可重复读和显式锁定。

13.4.2. 使用显式锁定强制一致性

当可以使用非可序列化写时,要保证一行的当前有效性并保护它不受并发更新的影响,我们必须使用SELECT FOR UPDATESELECT FOR SHARE或一个合适的LOCK TABLE 语句(SELECT FOR UPDATESELECT FOR SHARE锁只针对并发更新返回行,而LOCK TABLE会锁住整个表)。当从其他环境移植应用到PostgreSQL时需要考虑这些。

关于这些来自其他环境的转换还需要注意的是SELECT FOR UPDATE不保证一个并发事务将不会更新或删除一个被选中的行。要在PostgreSQL中这样做,你必须真正地更新该行,即便没有值需要被改变。SELECT FOR UPDATE 临时阻塞其他事务,让它们不能获取该相同的锁或者执行一个会影响被锁定行的UPDATEDELETE,但是一旦正持有该所锁的事务提交或回滚,一个被阻塞的事务将继续执行冲突操作,除非当锁被持有时一个该行的实际UPDATE被执行。

在非可序列化MVCC环境下,全局有效性检查需要一些额外的考虑。例如,一个银行应用可能会希望检查一个表中的所有扣款总和等于另外一个表中的收款总和,同时两个表还会被更新。比较两个连续的在读已提交模式下不会可靠工作的SELECT sum(...)命令, 因为第二个查询很可能会包含没有被第一个查询考虑的事务提交的结果。在一个单一的可重复读事务里进行两个求和则给出在可串行化事务开始之前提交的所有事务产生的准确结果 — 但有人可能会合理地置疑在结果被递交的时候,它们是否仍然相关。 如果可重复读事务本身在尝试做一致性检查之前应用了某些变更,那么检查的有用性就更加值得讨论了, 因为现在它包含了一些(但不是全部)事务开始后的变化。 在这种情况下,一个小心的人可能希望锁住所有需要检查的表,这样才能获得一个无可置疑的当前现状的图像。 一个SHARE模式(或者更高)的锁保证在被锁定表中除了当前事务所作的更改之外,没有未提交的更改。

还要注意如果某人正在依赖显式锁定来避免并发更改,那么他应该使用读已提交模式, 或者是在可重复读模式里在执行命令之前小心地获取锁。 在可重复读事务里获取的锁保证了不会有其它修改该表的事务正在运行,但是如果事务看到的快照在获取锁之前, 那么它可能早于表中一些现在已经提交的更改。 一个可重复读事务的快照实际上是在它的第一个查询或者数据修改命令(SELECTINSERTUPDATEDELETE)开始的时候冻结的,因此我们可以在快照冻结之前显式地获取锁。

本文转自PostgreSQL中文社区,原文链接:13.4. 应用级别的数据完整性检查

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
4月前
|
SQL 关系型数据库 C语言
PostgreSQL【应用 03】Docker部署的PostgreSQL扩展SQL之C语言函数(编写、编译、载入)计算向量余弦距离实例分享
PostgreSQL【应用 03】Docker部署的PostgreSQL扩展SQL之C语言函数(编写、编译、载入)计算向量余弦距离实例分享
45 0
|
4月前
|
SQL 关系型数据库 数据库
PostgreSQL【应用 02】扩展SQL之C语言函数(编写、编译、载入)实例分享
PostgreSQL【应用 02】扩展SQL之C语言函数(编写、编译、载入)实例分享
49 0
|
4月前
|
SQL 关系型数据库 MySQL
MySQL【实践 02】MySQL迁移到PostgreSQL数据库的语法调整说明及脚本分享(通过bat命令修改mapper文件内的SQL语法)
MySQL【实践 02】MySQL迁移到PostgreSQL数据库的语法调整说明及脚本分享(通过bat命令修改mapper文件内的SQL语法)
113 0
|
4月前
|
SQL 关系型数据库 PostgreSQL
PostgreSQL【SQL 01】根据条件更新字段值或追加信息STRPOS(string, substring)函数使用及LIKE函数对比
PostgreSQL【SQL 01】根据条件更新字段值或追加信息STRPOS(string, substring)函数使用及LIKE函数对比
56 0
|
4月前
|
SQL 关系型数据库 PostgreSQL
PostgreSQL【部署 01】离线安装PostgreSQL+PostGIS踩坑及问题解决经验分享(含安装文件PostgreSQL+PostGIS及多个依赖+测试SQL)
PostgreSQL【部署 01】离线安装PostgreSQL+PostGIS踩坑及问题解决经验分享(含安装文件PostgreSQL+PostGIS及多个依赖+测试SQL)
118 0
|
4月前
|
SQL NoSQL 关系型数据库
postgresql|数据库|SQL语句冲突的解决
postgresql|数据库|SQL语句冲突的解决
72 0
|
4月前
|
SQL 关系型数据库 编译器
PostgreSQL SQL扩展 ---- C语言函数(二)
可以用C(或者与C兼容,比如C++)语言编写用户自定义函数(User-defined functions)。这些函数被编译到动态可加载目标文件(也称为共享库)中并被守护进程加载到服务中。“C语言函数”与“内部函数”的区别就在于动态加载这个特性,二者的实际编码约定本质上是相同的(因此,标准的内部函数库为用户自定义C语言函数提供了丰富的示例代码)
67 0
|
15天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
52 10
|
1月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改
|
25天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
17 0