【postgresql 基础入门】事物transaction的开启,提交,回滚命令,自动提交设置
作者:mmseoamin日期:2024-03-20

事务transaction

​专栏内容:

  • postgresql内核源码分析
  • 手写数据库toadb
  • 并发编程

个人主页:我的主页

管理社区:开源数据库

座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

系列文章

  • 入门准备
  • postgrersql基础架构
  • 快速使用
  • 初始化集群
  • 数据库服务管理
  • psql客户端使用
  • pgAdmin图形化客户端
  • 数据库的使用
  • 创建数据库
  • 数据库操作
  • 表的使用
  • 表的创建
  • 表的操作
  • 数据查询
  • 数据查询
  • 多表联合查询
  • 数据操作
  • 插入数据的方式

    文章目录

    • 事务transaction
    • 系列文章
    • 一、概述
    • 二、事务介绍
    • 三、事务命令
      • 开启事务
      • 提交事务
      • 回滚事务
      • 四、自动提交配置
      • 五、总结
      • 六、结尾

        一、概述


        在数据库中,事务是所有工作任务的最小单位,它里面可以包括一条SQL,也可以包括多条SQL,它们一起完成。本文就来介绍postgresql中的事务命令begin、end、rollback的使用,在我们平常SQL中事务的应用。

        二、事务介绍


        在数据库原理当中,事务有四个特性ACID,这里再来回顾一下:

        • 原子性 Atomicity,事务内的所有操作一起完成,或者全部失败,事务是一个整体,不管包含多少条SQL,它们之间不可分割;
        • 一致性 Consistency,事务内修改的数据是有效的,同时满足定义的所有约束限制;
        • 隔离性 Isolation,不同的事务之间相互隔离,事务执行不受其它事务执行中间状态的影响,并发执行的事务互不干扰;
        • 持久性 Durability,事务被提交后,其对数据库的改变是永久的记录的,不会因为其它操作或者数据库的故障而受影响;即使数据库发生故障,也能够恢复到这个持久性的状态下;

          数据库的任务以事务为单位进行执行,而事务的这四个特性,保证了数据库事务的可靠性和稳定性,即使在多任务并发环境下,也能安全有效的执行,不会出现数据不一致或冲突。

          三、事务命令


          在postgresql中,事务操作基础命令有:

          • 开启事务
          • 提交事务
          • 回滚事务

            开启事务

            开始一个事务的命令为 BEGIN,也可以写为BEGIN WORK或 BEGIN TRANSACTION, 标识一个事务开始。

            下面准备一张表,然后插入一条数据,表还是前面博客常用的产品表,数据可以自行添加;

            -- 创建产品表  
            CREATE TABLE products (  
                product_id INT PRIMARY KEY,  
                product_name VARCHAR(255) NOT NULL,  
                price DECIMAL(10, 2) NOT NULL,  
                category VARCHAR(255)  
            ); 
            

            然后在命令行客户端中开始一个事务

            postgres=# begin;
            BEGIN
            postgres=*#
            postgres=*# select * from products ;
             product_id | product_name |  price  | category
            ------------+--------------+---------+----------
                      2 | shirt        |  202.40 | type2
                      3 | cake         |   37.80 | type4
                      5 | hat          |   88.40 | type2
                      6 | milk         |   19.80 | type4
                      1 | iphone       | 8999.01 | type5
                      7 | keyboard     |   92.01 | type5
                      4 | pencil       |   12.00 | type1
            (7 rows)
            postgres=*# update products set price = 8.2 where product_id=4;
            UPDATE 1
            

            可以看到命令行提示符postgres=*#中多了一个*,说明当前在事务中,此时可以继续执行SQL,而这些SQL在提交之前都会属于同一个事务。

            提交事务

            事务中的操作执行完成后,就需要提交事务,让操作结果真正生效。

            事务的提交命令为COMMIT, 或者对应的为COMMIT WORK或者COMMIT TRANSACTION,标识一个事务中的所有操作都真正持久的生效。

            接上个练习,将事务提交

            postgres=*# commit;
            COMMIT
            postgres=#
            

            可以看到事务提交命令执行后,命令行提示符中的*消失了,说明当前没有在事务当中。

            回滚事务

            在一个事务中包含很多操作时,如果错误的增加了一个操作时,这个事务就不能被提交,需要回退到事务开始之前的状态,然后重新开始,此时我们就要用到事务回滚命令ROLLBACK,或者对应的为ROLLBACK WORK或者ROLLBACK TRANSACTION。

            postgres=# begin;
            BEGIN
            postgres=*# select * from products ;
             product_id | product_name |  price  | category
            ------------+--------------+---------+----------
                      2 | shirt        |  202.40 | type2
                      3 | cake         |   37.80 | type4
                      5 | hat          |   88.40 | type2
                      6 | milk         |   19.80 | type4
                      1 | iphone       | 8999.01 | type5
                      7 | keyboard     |   92.01 | type5
                      4 | pencil       |    8.20 | type1
            (7 rows)
            postgres=*# update products set price = 7 where product_id=4;
            UPDATE 1
            postgres=*# select * from products ;
             product_id | product_name |  price  | category
            ------------+--------------+---------+----------
                      2 | shirt        |  202.40 | type2
                      3 | cake         |   37.80 | type4
                      5 | hat          |   88.40 | type2
                      6 | milk         |   19.80 | type4
                      1 | iphone       | 8999.01 | type5
                      7 | keyboard     |   92.01 | type5
                      4 | pencil       |    7.00 | type1
            (7 rows)
            postgres=*# rollback ;
            ROLLBACK
            
            • 首先开启一个新事务;
            • 然后查询products表的数据,更新产品id为4的价格为7
            • 再次查询products表的数据,可以看到id为4的产品价格更新为7,此时还在事务中,并不是持久结果;
            • 最后回滚事务,事务中的操作都不会生效,数据状态回退出事务执行前的状态

              下面我们验证一下数据库中的数据

              postgres=# select * from products ;
               product_id | product_name |  price  | category
              ------------+--------------+---------+----------
                        2 | shirt        |  202.40 | type2
                        3 | cake         |   37.80 | type4
                        5 | hat          |   88.40 | type2
                        6 | milk         |   19.80 | type4
                        1 | iphone       | 8999.01 | type5
                        7 | keyboard     |   92.01 | type5
                        4 | pencil       |    8.20 | type1
              (7 rows)
              postgres=*#
              

              可以看到数据库中产品ID为4的价格仍为8.20,没有因为上一个事务操作而变化;

              四、自动提交配置


              在前面的博客分享中,介绍了很多的SQL种类,也有很多案例,并没有看到事务的影子,这是怎么回事呢?

              这个秘密就在我们使用的客户端中,拿命令行客户端psql看一下;

              postgres=# \echo :AUTOCOMMIT
              on
              

              默认参数AUTOCOMMIT是打开的,这个参数是对客户端生效的,所以在我们输入单条SQL时,每个SQL默认为一个单独的事务,客户端帮我们自动提交了,使得我们看不到事务的效果。

              关闭自动提交开关后,看一下效果:

              postgres=# \set AUTOCOMMIT off
              postgres=# \echo :AUTOCOMMIT
              off
              

              执行一条SQL

              postgres=# select * from products ;
               product_id | product_name |  price  | category
              ------------+--------------+---------+----------
                        2 | shirt        |  202.40 | type2
                        3 | cake         |   37.80 | type4
                        5 | hat          |   88.40 | type2
                        6 | milk         |   19.80 | type4
                        1 | iphone       | 8999.01 | type5
                        7 | keyboard     |   92.01 | type5
                        4 | pencil       |   12.00 | type1
              (7 rows)
              postgres=*#
              postgres=*# commit;
              COMMIT
              postgres=#
              

              这时候会看到命令行提示符postgresql=*#中间会有一个*的符号,这说明还在事务中,需要手动提交事务,执行COMMIT之后才会消失。

              五、总结


              通过本文的分享,将SQL语句与数据库理论中的事务联系起来,数据库系统中任务都是以事务为单位进行执行,保障数据的完整性,一致性以及持久性。在我们执行SQL时,其实也是通过事务进行提交生效的,当然在其它客户端或者JDBC中也是一样的,可以利用事务的特性来保持数据一致性。

              六、结尾


              非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

              作者邮箱:study@senllang.onaliyun.com

              如有错误或者疏漏欢迎指出,互相学习。

              注:未经同意,不得转载!