【颗粒归仓】--数据库事务

2024-08-26 02:38

本文主要是介绍【颗粒归仓】--数据库事务,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   说到事务,做IT的肯定都不陌生,会想到Transcation(开启、提交、回滚)。作为资深的IT工作者,对事务全面理解是一项基本功,当然对于正在迈向资深的我来说,也必须了解。下面就来谈一下事务

 一、事务的概念

   数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 


 二、事务的特性

  事务必须具备ACID四个特性

  原子性(Atomicity): 一个事务的执行被视为一个不可分割的单元,事务中的操作,要么全部成功,要么全部失败回滚,不能只执行其中的一部分。

  一致性(Consistency):一致性是指事务必须使数据库从一个一致的状态变到另一个一致的状态,也就是执行事务的前后状态都必须处于一致的状态。比如说A向B转账500,那么A账户要减500,而B账户需要加500,这两个事件最终的账户总额仍然没有改变。

  隔离性(Isolation):是指事务之间的行为互不影响,在实际操作中,会受事务的隔离级别的影响。

  持久性(Durability):事务提交之后,将数据持久到数据库,即使系统出现问题,数据依然还在。


 三、事务的隔离级别

  在说到事务的隔离特性时,提到事务的隔离性会受到隔离级别的影响。事务的隔离级别定义了事务之间的可见性,有人称它为事务的“自私”程度。主要分为四种隔离级别

  1、READ UNCOMMITTED(未提交读)。

     在此隔离级别下,如果事务A对数据进行修改,在没有提交的情况下,事务B也可以看到该修改,这种问题称为脏读。未提交读的隔离级别较低,容易引起很多问题,一般不常用。

     测试如下:(使用navicat连接mysql进行测试)

     ①首先要将隔离级别设置为未提交读状态(以下实例都在global级别设置,也可以设置session级别)

      打开第一个命令行界面,用来专门设置隔离级别:

      mysql> set @@global.tx_transaction='READ-UNCOMMITTED';

      因为设置的是global级别的,所以在接下来的操作中,为了能更好的演示效果,需要另开一个命令行窗口,在接下来的描述中,提到创建事务就表示新打开一个窗口。

      ②创建A事务:

        首先要查看当前的隔离级别,确保是未提交读状态:

        

        开启事务,并执行查询,可以看到只有三条数据。结果如下:

        

       ③创建B事务:

         也是先查看当前的隔离级别(以下测试都会在新打开命令行界面时查看隔离级别,后面就不再叙述)

         开启事务,并插入一条数据,但是不提交。此时,在当前事务中可以查询到新增的数据:

         

       ④然后再回到A事务,执行查询,此时在B事务还未提交时,就可以查到新增的数据:

       

      在A事务中读到了B事务未提交的数据,称此现象为脏读。


  2、READ COMMITTED(提交读)

    在该隔离级别下,不会出现脏读。当事务A对数据修改之后,只要在提交以后,事务B才能看到修改的数据。但是会出现不可重复读问题,何谓不可重复读?就是一个事务对同一行数据重复读取两次,但是却得到了不同的结果。

    测试如下:

     ①设置隔离级别

       mysql> set @@global.tx_isolation='READ-COMMITTED';

     ②创建事务A:

       开启事务,然后查询数据

       

      ③创建事务B

        开启事务,接下来查看数据,跟事务A查到的数据一致。然后更新第二条数据。此时,不提交事务。

        

       ④在事务A中执行查询命令,发现B事务更新的数据查不到:

       

       ⑤让事务B提交,然后事务A再次执行查询,此时就可以查看到更新之后的数据:

       

     在该隔离级别下,事务A读到的内容是事务B提交后的数据,即事务A只能读到事务B两端的数据,至于事务B中间的其他修改就读不到了。如事务A能读到刚开始的状态,如果事务B在修改过程中,刚开始把id=10的数据修改为‘cc’,没有提交;然后又把id=11的数据改为‘dd’,依旧不提交;最后发现更新错了,又把id=10的数据改为‘c’,id=11的数据改为‘d’,把id=9的数据改为‘bb’,提交。此时事务A只能读到id=9的值变了,至于id=10和11的变化过程一无所知。这个就是与未提交读的区别之处,未提交读能看到这个变化过程,随变化而变化。

  3、REPEATABLE  READ(可重复读)

     在该隔离级别下,不会出现不可重复读的问题。事务B对数据做的修改,提交之后,对于先于B事务开启的事务A来说,此修改仍然看不到。

     测试如下:

      ①设置隔离级别

        mysql> set@@global.tx_isolation='REPEATABLE-READ';

      ②创建事务A

        开启事务,然后执行查询

        

      ③创建事务B

        开启事务B,先查询数据,然后将第三条数据更新。此时不提交事务

        

     ④在事务A中进行查询,无法查看事务B修改的数据

     ⑤提交事务B,再在事务A中执行查询,依然无法看到更新的数据,查询到的数据始终没有改变

     

     ⑥将事务A提交,然后开启新的事务,此时即可查看到更新后的数据


   可重复读解决了不可重复读的问题,某个事务在执行期间,无论后续的其他事务如何操作数据,都保持查询结果不变,但是重新打开事务后,会读到不一样的数据。这就引出了幻读的问题,所问幻读就是事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据或者缺少了第一次查询中出现的数据。


  4、SERIALIZABLE(可串行化)

   这是隔离的最高级别,强制要求所有的事务串行执行,会对每行数据加锁,这就造成大量锁征用问题,性能最差。

   测试如下:

    ①设置隔离级别

       mysql>  set @@global.tx_isolation='SERIALIZABLE';

    ②创建事务A

      开启事务并执行查询

      

    ③创建事务B

      开启事务并执行查询,此时可以查询。但是如果更新数据时,事务处于等待状态,因为事务A已经上锁。当一定时间还无法执行时,提示当前更新数据处于锁状态,无法更新。

      

     ④当事务A提交后,处于等待状态的事务B也会执行完。

     

    可串行化解决了幻读的问题,但是又引发了新的问题,死锁。例如上述两个事务,如果都不提交,那么此时都将无法进行后续操作。


   综合上述内容,四种隔离级别所解决的问题如下:

   

   其性能如下:

   

     即隔离级别越高,其并发性越低,性能越差。


  四、小结

    事务是开发中无法避免的一个问题,所以熟悉事务的基本概念以及使用是非常重要的。当然本文也只是解析了事务的一角,还需要在今后的工作中继续深入剖析事务的应用。

  

这篇关于【颗粒归仓】--数据库事务的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1107314

相关文章

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

MySQL数据库中ENUM的用法是什么详解

《MySQL数据库中ENUM的用法是什么详解》ENUM是一个字符串对象,用于指定一组预定义的值,并可在创建表时使用,下面:本文主要介绍MySQL数据库中ENUM的用法是什么的相关资料,文中通过代码... 目录mysql 中 ENUM 的用法一、ENUM 的定义与语法二、ENUM 的特点三、ENUM 的用法1

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

嵌入式数据库SQLite 3配置使用讲解

《嵌入式数据库SQLite3配置使用讲解》本文强调嵌入式项目中SQLite3数据库的重要性,因其零配置、轻量级、跨平台及事务处理特性,可保障数据溯源与责任明确,详细讲解安装配置、基础语法及SQLit... 目录0、惨痛教训1、SQLite3环境配置(1)、下载安装SQLite库(2)、解压下载的文件(3)、

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

MySQL追踪数据库表更新操作来源的全面指南

《MySQL追踪数据库表更新操作来源的全面指南》本文将以一个具体问题为例,如何监测哪个IP来源对数据库表statistics_test进行了UPDATE操作,文内探讨了多种方法,并提供了详细的代码... 目录引言1. 为什么需要监控数据库更新操作2. 方法1:启用数据库审计日志(1)mysql/mariad

postgresql数据库基本操作及命令详解

《postgresql数据库基本操作及命令详解》本文介绍了PostgreSQL数据库的基础操作,包括连接、创建、查看数据库,表的增删改查、索引管理、备份恢复及退出命令,适用于数据库管理和开发实践,感兴... 目录1. 连接 PostgreSQL 数据库2. 创建数据库3. 查看当前数据库4. 查看所有数据库

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

Oracle 数据库数据操作如何精通 INSERT, UPDATE, DELETE

《Oracle数据库数据操作如何精通INSERT,UPDATE,DELETE》在Oracle数据库中,对表内数据进行增加、修改和删除操作是通过数据操作语言来完成的,下面给大家介绍Oracle数... 目录思维导图一、插入数据 (INSERT)1.1 插入单行数据,指定所有列的值语法:1.2 插入单行数据,指