PostgreSql 事务

这篇具有很好参考价值的文章主要介绍了PostgreSql 事务。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、事务的 ACID 特性

  在日常操作中,对于一组相关操作,通常需要其全部成功或全部失败。在关系型数据库中,将这组相关操作称为事务。事务具有的四个特性简称为 ACID。

  • 原子性(Atomicity):保证事务中的操作要么全部成功,要么全部失败,不会只成功一部分。
  • 一致性(Consistency):数据修改的有效性,并且遵循一定的业务规则。
  • 隔离性(Isolation):决定了并发事务之间的可见性和相互影响程度。
  • 持久性(Durability):确保已经提交的事务必须永久生效。

二、事务的使用

2.1 自动提交事务

postgres=# \echo :AUTOCOMMIT
on
postgres=# create table accounts(id serial primary key,user_name varchar(50),balance numeric(10,4));
CREATE TABLE
postgres=# alter table accounts add constraint bal_check check(balance >= 0);
ALTER TABLE
postgres=# insert into accounts(user_name, balance) values ('usera', 6000);
INSERT 0 1
postgres=# table accounts;
 id | user_name |  balance
----+-----------+-----------
  1 | usera     | 6000.0000
(1 row)

2.2 手动提交事务

postgres=# \set AUTOCOMMIT off
postgres=# \echo :AUTOCOMMIT
off
postgres=# begin;
BEGIN
postgres=*# insert into accounts(user_name, balance) values ('userb', 0);
INSERT 0 1
postgres=*# table accounts;
 id | user_name |  balance
----+-----------+-----------
  1 | usera     | 6000.0000
  2 | userb     |    0.0000
(2 rows)

postgres=*# commit;
COMMIT
postgres=# table accounts;
 id | user_name |  balance
----+-----------+-----------
  1 | usera     | 6000.0000
  2 | userb     |    0.0000
(2 rows)

2.3 手动回滚事务

postgres=# begin;
BEGIN
postgres=*# insert into accounts(user_name, balance) values ('userc', 2000);
INSERT 0 1
postgres=*# table accounts;
 id | user_name |  balance
----+-----------+-----------
  1 | usera     | 6000.0000
  2 | userb     |    0.0000
  3 | userc     | 2000.0000
(3 rows)

postgres=*# rollback;
ROLLBACK
postgres=# table accounts;
 id | user_name |  balance
----+-----------+-----------
  1 | usera     | 6000.0000
  2 | userb     |    0.0000
(2 rows)

2.4 手动回滚事务至保存点

postgres=# begin;
BEGIN
postgres=*# insert into accounts(user_name, balance) values ('userc', 2000);
INSERT 0 1
postgres=*# savepoint sv1;
SAVEPOINT
postgres=*# insert into accounts(user_name, balance) values ('userd', 0);
INSERT 0 1
postgres=*# table accounts;
 id | user_name |  balance
----+-----------+-----------
  1 | usera     | 6000.0000
  2 | userb     |    0.0000
  4 | userc     | 2000.0000
  5 | userd     |    0.0000
(4 rows)

postgres=*# rollback to sv1;
ROLLBACK
postgres=*# commit;
COMMIT
postgres=# table accounts;
 id | user_name |  balance
----+-----------+-----------
  1 | usera     | 6000.0000
  2 | userb     |    0.0000
  4 | userc     | 2000.0000
(3 rows)

三、并发与隔离

多个用户访问相同数据时,可能导致如下问题:

  • 脏读(dirty read):一个事务能够读取其他事务未提交的修改。
  • 不可重复读(nonrepeatable read):一个事务读取某个记录后,再次读取该记录时数据发生了改变(被其他事务修改并提交)。
  • 幻读(phantom read):一个事务按照某个条件查询一些数据后,再次执行相同查询时结果的数量发生了变化(另一个事务增加或者删除了某些数据并且完成提交)。幻读和非重复读有点类似,都是由于其他事务修改数据导致的结果变化。
  • 更新丢失(lost update):当两个事务同时读取某一记录,然后分别进行修改提交,就会造成先提交的事务的修改丢失。

为了解决并发问题, SQL 标准定义了 4 种不同的事务隔离级别(从低到高):

  • Read Uncommitted(读未提交):最低的隔离级别,实际上就是不隔离,任何事务都可以看到其他事务未提交的修改;该级别可能产生各种并发异常。不过,PostgreSQL 消除了 Read Uncommitted 级别时的脏读,因为它的实现等同于 Read Committed。
  • Read Committed(读已提交):一个事务只能看到其他事务已经提交的数据,解决了脏读问题,但是存在不可重复读、幻读和更新丢失问题。这是 PostgreSQL 的默认隔离级别。
  • Repeated Read(可重复读):一个事务对于同某个数据的读取结果不变,即使其他事务对该数据进行了修改并提交;不过如果其他事务删除了该记录,则无法再查询到数据(幻读)。SQL 标准中的可重复读可能出现幻读,但是 PostgreSQL 在可重复读级别消除了幻读。
  • Serializable(可串行化):最高的隔离级别,事务串行化执行,没有并发。
隔离级别 脏读 不可重复读 幻读 更新丢失
Read Uncommitted 可能,但 PostgreSQL 不会 可能 可能 可能
Read Committed 不可能 可能 可能 可能
Repeatable Read 不可能 不可能 可能,但 PostgreSQL 不会 不可能
Serializable 不可能 不可能 不可能 不可能

修改隔离级别示例

--显示数据库隔离级别
show transaction_isolation;

--事务中修改隔离级别
begin;
set transaction isolation level {serializable|repeatable read|read committed|read uncommitted};
……
……
commit;

四、两阶段提交

  PostgreSQL 数据库支持两阶段提交协议(默认禁用此功能,仅在分布式架构中使用)。在分布式系统中,事务中往往包含了多台数据库上的操作,虽然单台数据库的操作能够保证原子性,但多台数据库之间的原子性就需要通过两阶段提交来实现了,两阶段提交是实现分布式事务的关键。

  两阶段提交协议有如下 5 个步骤:

  • 应用程序先调用各台数据库做一些操作,但不提交事务。然后应用程序调用事务协调器(该协调器可能也是由应用自己实现的)中的提交方法。
  • 事务协调器将联络事务中涉及的每台数据库,并通知它们准备提交事务,这是第一阶段的开始,此时 PostgreSQL 中调用 PREPARE TRANSACTION 命令。
  • 各台数据库接收到 PREPARE TRANSACTION 命令后,PostgreSQL 会将已准备好提交的信息写入持久存储区中,如果无法完成此,会直接返回失败给事务协调器。
  • 事务协调器接收所有数据库的响应。
  • 在第二阶段,如果任何一个数据库在第一阶段返回失败,则事务协调器将会发一个回滚命令 “ROLLBACK PREPARED” 给各台数据库。如果所有数据库的响应都是成功的,则向各台数据库发送 COMMIT PREPARED 命令,通知各台数据库事务成功。

示例文章来源地址https://www.toymoban.com/news/detail-610490.html

--修改 max_prepared_transactions 参数,重启数据库生效
show max_prepared_transactions;
alter system set max_prepared_transactions = 10;
pg_ctl restart
show max_prepared_transactions;

--创建测试表
create table testtab01(id int primary key);

--开启事务,插入数据并进行第一阶段提交
postgres=# begin;
BEGIN
postgres=*# insert into testtab01 values(1);
INSERT 0 1
postgres=*# PREPARE TRANSACTION 'osdba_global_trans_0001';
PREPARE TRANSACTION
postgres=# table testtab01;
 id
----
(0 rows)

--重启数据库后进行第二阶段提交
[postgres@localhost ~]$ pg_ctl restart
waiting for server to shut down.... done
server stopped
waiting for server to start....2023-07-24 17:01:33.206 CST [10882] LOG:  00000: redirecting log output to logging collector process
2023-07-24 17:01:33.206 CST [10882] HINT:  Future log output will appear in directory "logs".
2023-07-24 17:01:33.206 CST [10882] LOCATION:  SysLogger_Start, syslogger.c:674
 done
server started
[postgres@localhost ~]$ psql
psql (13.6)
Type "help" for help.

postgres=# table testtab01;
 id
----
(0 rows)

postgres=# COMMIT PREPARED 'osdba_global_trans_0001';
COMMIT PREPARED
postgres=# table testtab01;
 id
----
  1
(1 row)

到了这里,关于PostgreSql 事务的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Postgresql数据库死锁

    ERROR: deadlock detected DETAIL: Process 95 waits for ShareLock on transaction 3553457; blocked by process 187. Process 187 waits for ShareLock on transaction 3553458; blocked by process 95. HINT: See server log for query details. CONTEXT: while updating tuple (0,6) in relation “deadlock_example” 其中 Process 95 在等待共享锁(ShareLock)的事务

    2024年01月20日
    浏览(58)
  • PostgreSQL 创建数据库

    PostgreSQL 创建数据库可以用以下三种方式: CREATE DATABASE 命令需要在 PostgreSQL 命令窗口来执行,语法格式如下: 例如,我们创建一个 runoobdb 的数据库: createdb 命令创建数据库 createdb 是一个 SQL 命令 CREATE DATABASE 的封装。 参数说明: . dbname:要创建的数据库名。 . description:关

    2024年02月12日
    浏览(44)
  • 【数据库】什么是 PostgreSQL?开源数据库系统

    PostgreSQL 是一个开源的对象关系数据库系统,本文,我们将讨论 PostgreSQL、它的用途和好处。 PostgreSQL 是由 PostgreSQL Global Development Group 开发的高级 开源关系数据库管理系统(RDBMS) 。它作为 POSTGRES 项目的一部分于 1986 年在加州大学伯克利分校启动,它最初于 1996 年 7 月 8 日发布

    2023年04月08日
    浏览(39)
  • postgresql数据库定时备份到远程数据库

    1.老规矩,服务器目录结构: conf目录无内容 profile: 其中: 最后一行 export PGPASSWORD=‘root’ 是需要备份的数据库的密码,因为直接用 pg_dump 命令备份需要输入密码交互,而我们需要达到自动备份,所以借助这种方式不需要输入密码 docker-compose.yml: 启动容器: 然后再data目录下面

    2024年02月09日
    浏览(38)
  • postgresql 数据库 索引 介绍

    大家在学习数据库的时候,是不是常常听到索引?那什么是索引呢?索引有哪些作用呢?索引有哪些种类呢?为什么要建索引呢?带着这些疑问,本文带你一起学习postgresql数据库的索引。 索引是提高数据库性能的常用途径。比起没有索引,使用索引可以让数据库服务器更快

    2024年02月13日
    浏览(50)
  • postgresql-数据库与模式

    数据库管理系统( DBMS )是用于管理数据库的软件系统。常见的关系型DBMS有PostgreSQL、 MySQL、Oracle、Microsoft SQL Server、SQLite 等。常见的 NoSQL 数据库有 Redis、MongoDB、 Cassandra、Neo4j 等。PostgreSQL 荣获了数据库排名网站DB-Engines 2017、2018 以及 2020 年度数据库管理系统称号 PostgreSQL 数

    2024年02月08日
    浏览(46)
  • PostgreSQL连接指定数据库

    要连接到PostgreSQL中的指定数据库,您需要使用以下格式的连接字符串: 其中,username是连接PostgreSQL的用户名,password是该用户的密码,hostname是PostgreSQL服务器的主机名或IP地址,port是PostgreSQL服务器的端口号,database_name是要连接的数据库名称。 例如,如果您要连接到名为my

    2024年02月11日
    浏览(39)
  • Python操作PostgreSQL数据库

    个人简介 :一个从会计转行数据分析师的三旬老汉 擅长领域 :数据分析、数据仓库、大数据 博客内容 :平时会将自己工作中遇到的问题进行归纳总结,分享给各位小伙伴,意在帮助大家 少加班 、 不掉发 ,让我们相互学习,一起进步。 本文分享使用Python操作PostgreSQL数据

    2024年02月15日
    浏览(38)
  • PostgreSQL数据库定时备份脚本

          大多数数据库管理系统都提供了自带的备份工具,可以使用这些工具来进行备份操作。     例如: MySQL:使用 mysqldump 命令进行备份。 PostgreSQL:使用 pg_dump 命令进行备份。       以下是一个用于定时备份 PostgreSQL 数据库的示例脚本。这个脚本将使用 pg_dump 工具来创建

    2024年02月11日
    浏览(40)
  • python连接postgresql数据库

    postgresql是常用的关系型数据库,并且postgresql目前还保持着全部开源的状态,所以我们今天就一起来学习一下,如何用python连接postgresql。 官方文档地址: https://www.psycopg.org/docs/cursor.html 若是增、删、更等操作,则操作流程为: connect 连接 获取游标对象 cursor 执行sql得到结果

    2024年02月16日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包