为什么数据库事务会出现未知状态,如何处理
数据库的事务是原子操作,要么成功,要么失败。但是实际上在客户端的视角,可能有第三种状态:unknown状态。
当客户端提交事务结束(rollback , commit , prepare xact , rollback pxact , commit pxact)的请求后,数据库收到请求,数据库可能执行失败,也可能执行成功,不管怎样都要写对于的WAL日志,还有CLOG,然后数据库要将执行结果返回给客户端ACK。
这里存在几种可能,导致客户端不知道执行到底怎么样了?
收到客户端请求后,数据库没有返回任何ACK给客户端,客户端对这次请求很茫然,它只能人为数据库处于UNKNOWN的状态。
UNKNOWN 事务的处理unknown事务,就是客户端没有收到commit/rollback ACK的事务。不知道是成功还是失败。
多节点(quorum based sync replication)与单节点都可能出现UNKNOWN事务,效果、形态一致。
如何处理unknown事务呢?
unknown事务分为以下几种情况.
rollback , commit , prepare xact , rollback pxact , commit pxact 几种情况的unknown处理方法:
1、两阶段解决unknown状态问题
prepare 阶段unknown, 切换leader后,客户端通过pg_prepared_xacts视图检查prepare xact状态,如果没有prepare xact则说明失败了,那么整个事务重新发起即可。如果prepare xact存在,说明prepare xact成功了。
commit or rollback prepare xact阶段unknown, 切换后检查prepare xact状态,存在则重试commit or rollback prepare xact。不存在则说明已经成功(我们认为2PC是一定成功的),无须处理。
2、非两阶段事务,rollback unknown无须处理,rollback失败或成功对于客户端来说结果是一样的。因为不管怎样都会回滚掉,这是数据库原子性保障的。
3、非两阶段事务,commit unknown处理,极度严谨的场景,程序可以设计事务状态可回溯,例如:
事务开始时,记录事务号或唯一流水号,事务号在数据库中是一个唯一的流水,可以根据事务号查询它的状态,比如postgresql。
但是并不是所有数据库都有这种接口,比如非物理流式复制的数据库,则可以在事务中增加全局唯一流水号来查看事务是否提交。这里利用了事务的原子特性,既要么全成功要么全失败。可以举个使用例子。
使用业务流水实现事务状态判断的例子:
begin; 生成唯一业务流水ID, 写入到某个流水表,同时在程序或其他数据库中记录这个流水号,备查。 执行事务 提交事务; -- 出现unknown 通过唯一业务流水ID,查询数据库中是否存在这条记录。 如果不存在,说明事务提交失败。 如果存在,说明事务提交成功。(因为数据库的事务是原子操作)
事务解释 事务是我们保证数据正确性的重要手段,只要和数据库打交道,就得理解它的 ACID 特性,这也是一个专业程序员应该掌握的基本技能。
队列读取器代理在连接“PublicationServer”上的“pubDB”时遇到错误“试图进行的插入或更新已失败, 原因是目标视图或者目标视图所跨越的某一视图指定了 WITH CHECK OPTION, 而该操作的一个或多个结果行又不符合 CHECK OPTION 约束。
相关文章
- thinkphp6:mysql数据库使用事务(php 8.1.1 / thinkphp v6.0.10LTS)
- PostgreSQL 9.6 引领开源数据库攻克多核并行计算难题
- sql数据库为null时候ASP语句判断问题
- 使用SQL Server Profiler跟踪数据库
- Oracle 数据库中日期时间的插入操作
- mysql 查看数据库大小
- 基于CNN卷积神经网络的minst数据库手写字识别matlab仿真
- NoSQL数据库介绍(2)
- B-树(B-Tree)与二叉搜索树(BST):讲讲数据库和文件系统背后的原理(读写比较大块数据的存储系统数据结构与算法原理)...
- java连接数据库的模糊查询
- PostgreSQL的学习心得和知识总结(五十三)|语法级自上而下完美实现MySQL数据库的 insert set 的实现方案
- 查看mysql一些命令的数据库状态
- 解决navicat无法连接sqlserver数据库的问题
- [ 云计算 | Azure ] 配置Azure Database for MySQL数据库的时区