SQL 之 事务(Transaction)

SQL 之 事务

    • 一、什么是事务?
    • 二、事务的四大特性(ACID)
      • 1. 原子性(Atomicity)
      • 2. 一致性(Consistency)
      • 3. 隔离性(Isolation)
      • 4. 持久性(Durability)
    • 三、并发事务带来的问题
      • 1. 脏读(Dirty read)
      • 2. 修改丢失(Lost to modify)
      • 3. 不可重复读(Unrepeatableread)
      • 4. 幻读(Phantom read)
      • 不可重复读和脏读、幻读的区别
    • 四、事务的隔离级别
      • 4.1 SQL 标准定义了四个隔离级别
      • 4.2 隔离级别可解决的事务问题
      • 4.3 MySQL 之 查看与修改隔离级别
    • 五、事务的创建
    • 六、事务的传播特性
    • 七、数据库的锁机制
        • 7.1 按锁类型划分,可分为共享锁、排他锁
        • 7.2 按锁的粒度划分,可分为表级锁、行级锁、页级锁
        • 7.3 按使用机制划分,可分为乐观锁、悲观锁


一、什么是事务?

事务是逻辑上的一组操作,是由一系列对系统中数据进行访问与更新的操作所组成的一个 程序执行逻辑单元(Unit)
要么都执行,要么都不执行
 

一个最经典的例子 ------ 转账:
A用户向B用户转账100元,这里涉及两个数据操作:A用户账户减少100,B用户账户增加100。如果在两个操作之间数据库崩溃了,导致A少了B没增加,这就麻烦了。所以:
事务就是要保证这两个操作要么都完成,要么都不完成。

 

二、事务的四大特性(ACID)

在这里插入图片描述

1. 原子性(Atomicity)

事务是最小的执行单位,不允许分割。事务的原子性确保动作要么都执行,要么都不执行

2. 一致性(Consistency)

执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的。

事务执行的结果必须是使数据库从一个一致性状态转变到另一个一致性状态,因此当数据库只包含成功事务提交的结果时,就能说数据库处于一致性状态。
而如果数据库系统在运行过程中发生故障, 有些事务尚未完成就被迫中断,这些未完成的事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。

3. 隔离性(Isolation)

指 在并发环境中,并发的事务是相互隔离的,一个事务的执行不能被其他事务干扰,各并发事务之间数据库是独立的

不同的事务并发操纵相同的数据时,每个事务都有各自完整的数据空间,即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的 各个事务之间不能互相干扰。

4. 持久性(Durability)

在一个事务被提交之后,它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

 

三、并发事务带来的问题

当多个事务并发运行,经常会操作相同的数据来完成各自的任务(即多个用户对同一数据进行操作)。如果没有采取必要的隔离机制就会产生并发问题。
 

1. 脏读(Dirty read)

脏读是指 在一个事务处理过程里读取了另一个未提交的事务中的数据

当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问并使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。

2. 修改丢失(Lost to modify)

两个事务T1和T2读取同一个数据并修改,T2提交的结果覆盖了T1提交的结果,导致T1的修改被丢失
在一个事务读取一个数据时,另一个事务也访问了该数据,如果在第一个事务中修改了这个数据后,第二个事务也修改了这个数据,那么第一个事务内的修改结果就会丢失,因此称为修改丢失。

例如:
事务T1读取某表中的数据A=20,事务T2也读取A=20,事务T1修改A=A-1,事务T2也修改A=A-1,最终结果A=19,事务T1的修改被丢失。

3. 不可重复读(Unrepeatableread)

在一个事务内,多次读取同一数据,并且在这个事务还没结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。

例如:
事务T1在读取某一数据时,事务T2立马修改了该数据并提交给数据库,事务T1再次读取该数据时就得到了不同的结果,发生了不可重复读。

4. 幻读(Phantom read)

幻读又称虚读。
一个事务T1读取了几行数据,接着另一个并发事务T2插入了一些数据,当事务T1再次进行查询时就会发现多了一些原本不存在的记录(由事务T2插入的记录),就好像发生了幻觉一样,所以称为幻读。

不可重复读和脏读、幻读的区别

不可重复读和脏读的区别

脏读是某一事务读取了另一个事务未提交的脏数据;
不可重复读则是读取了前一事务提交的数据。

不可重复读和幻读区别

幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
 
不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改;
幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。

 

四、事务的隔离级别

4.1 SQL 标准定义了四个隔离级别

  1. READ-UNCOMMITTED(读取未提交数据)

    最低的隔离级别,允许读取尚未提交的数据变更
    避免了修改丢失,可能会导致脏读、幻读或不可重复读

    如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。
    该隔离级别可以通过“排他写锁”实现。

  2. READ-COMMITTED(读取已提交数据)

    允许读取并发事务已经提交的数据
    可以阻止脏读,但是幻读或不可重复读仍有可能发生

    读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。

  3. REPEATABLE-READ(可重复读)

    对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改
    可以阻止脏读和不可重复读,但幻读仍有可能发生

    这种隔离级别可以通过“共享读锁”和“排他写锁”实现。

    MySQL 默认的隔离级别 是 可重复读

  4. SERIALIZABLE(可串行化)

    最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,但是代价最高,性能最低。
    可以防止脏读、不可重复读以及幻读

    提供严格的事务隔离。它要求事务串行化执行,事务只能一个接着一个地执行,但不能并发执行。
    如果仅仅通过“行级锁”是无法实现事务串行化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

4.2 隔离级别可解决的事务问题

隔离级别修改丢失脏读不可重复读幻读
READ-UNCOMMITTEDxxx
READ-COMMITTEDxx
REPEATABLE-READx
SERIALIZABLE

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

大多数数据库的默认级别就是 读取已提交 Read committed,比如Sql Server , Oracle。
MySQL 默认级别是 可重复读 Repeatable-Read

 
这里需要注意的是

    与 SQL 标准不同的地方在于 InnoDB 存储引擎在 REPEATABLE-READ(可重复读)事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生 ,这与其他数据库系统(如 SQL Server) 是不同的。所以说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重复读) 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的 SERIALIZABLE(可串行化) 隔离级别。
    因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 READ-COMMITTED(读取提交内容) ,但是你要知道的是InnoDB 存储引擎默认使用 REPEATABLE-READ(可重复读) 并不会有任何性能损失。

InnoDB 存储引擎在 分布式事务 的情况下一般会用到 SERIALIZABLE(可串行化) 隔离级别。

4.3 MySQL 之 查看与修改隔离级别

  1. 通过SELECT @@tx_isolation;命令来查看

    mysql> SELECT @@tx_isolation;
    +-----------------+
    | @@tx_isolation  |
    +-----------------+
    | REPEATABLE-READ |
    +-----------------+
    
  2. 设置隔离级别

    set  [glogal | session]  transaction isolation level 隔离级别名称;
    set tx_isolation=’隔离级别名称;set transaction isolation level repeatable read;
    set tx_isolation=repeatable-read

    设置数据库的隔离级别一定要是在开启事务之前!

    使用JDBC对数据库的事务设置隔离级别:

    在调用Connection对象的setAutoCommit(false)方法之前。调用Connection对象的setTransactionIsolation(level)即可设置当前链接的隔离级别,至于参数level,可以使用Connection对象的字段:
    在这里插入图片描述

    代码如下:

    Connection conn = null;
    Statement st = null;
    ResultSet rs = null;try{conn = JdbcUtils.getConnection();//设置该链接的隔离级别conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);conn.setAutoCommit(false);	//开启事务
    }
    

    隔离级别的设置只对当前链接有效。对于使用MySQL命令窗口而言,一个窗口就相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效;对于JDBC操作数据库来说,一个Connection对象相当于一个链接,而对于Connection对象设置的隔离级别只对该Connection对象有效,与其他链接Connection对象无关。

 

五、事务的创建

  • 隐式事务:事务没有明显的开启和结束的标记
  • 显式事务:事务具有明显的开启和结束的标记 前提:必须先设置自动提交功能为禁用
步骤1:开启事务set autocommit=0;start transaction; 可选的,显式的开启一个事务。
步骤2:编写事务中的sql语句(select insert update delete)语句1语句2
步骤3:结束事务commit; 提交事务,并使已对数据库进行的所有修改称为永久性的。rollback; 回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。

 

六、事务的传播特性

  1. PROPAGATION_REQUIRED:默认事务类型,如果没有,就新建一个事务;如果有,就加入当前事务。适合绝大多数情况。

  2. PROPAGATION_REQUIRES_NEW:如果没有,就新建一个事务;如果有,就将当前事务挂起。

  3. PROPAGATION_NESTED:如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。

  4. PROPAGATION_SUPPORTS:如果没有,就以非事务方式执行;如果有,就使用当前事务。

  5. PROPAGATION_NOT_SUPPORTED:如果没有,就以非事务方式执行;如果有,就将当前事务挂起。即无论如何不支持事务。

  6. PROPAGATION_NEVER:如果没有,就以非事务方式执行;如果有,就抛出异常。

  7. PROPAGATION_MANDATORY:如果没有,就抛出异常;如果有,就使用当前事务。

 

七、数据库的锁机制

7.1 按锁类型划分,可分为共享锁、排他锁

共享锁(Share Locks,也叫读锁、S锁)

多个事务可封锁一个共享页;
任何事务都不能修改该页;
通常是该页读取完毕,S锁立即被释放。
在执行select语句的时候需要给操作对象(表或者一些记录 )加上共享锁,但加锁之前需要检查是否有排他锁,如果没有,则可以加共享锁(一个对象上可以加n个共享锁),否则不行。
共享锁的释放通常在执行完select语句之后,当然也有可能是在事务结束(包括正常结束和异常结束)的时候被释放,主要取决于数据库所设置的事务隔离级别。
 
其他用户可以并发读取数据,但任何事务都不能获取数据上的排他锁,直到已释放所有共享锁。
若事务T对数据对象A加上S锁,则事务T只能读A;其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

排他锁(Exclusive Lock,也叫写锁、X锁)

仅允许一个事务封锁此页;
其他任何事务必须等到X锁被释放才能对该锁页进行访问;
X锁一直到事务结束才能被释放。
执行insert、update、delete语句的时候需要给操作的对象加排他锁,在加排他锁之前必须确认该对象上没有其他任何锁,一旦加上排他锁之后,就不能再给这个对象加其他任何锁。
排他锁的释放通常是在事务结束的时候(当然也有例外,就是在数据库事务隔离级别被设置成Read Uncommitted(读未提交数据)的时候,这种情况下排他锁会在执行完更新操作之后被释放,而不是在事务结束的时候)。
 
若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。它防止任何其它事务获取资源上的锁,直到在事务的末尾将资源上的原始锁释放为止。在更新操作(INSERT、UPDATE 或 DELETE)过程中始终应用排它锁。

两者的区别

共享锁:如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不 能加排他锁。获取共享锁的事务只能读数据,不能修改数据。

排他锁:如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获取排他锁的事务既能读数据,又能修改数据。

7.2 按锁的粒度划分,可分为表级锁、行级锁、页级锁

表级锁

直接锁定整张表,在锁定期间,其他进程无法对该表进行写操作。如果你是写锁,则其他进程读也不允许。
特点是:开销小、加锁快,不会出现死锁。锁定粒度最大,发生锁冲突的概率最高,并发度最低
 
MYISAM存储引擎采用的就是表级锁。

行级锁

仅对指定的记录进行加锁,这样其他进程还是可以对同一个表中的其他记录进行操作。
特点:开销大,加锁慢,会出现死锁。锁定的粒度最小,发生锁冲突的概率最低,并发度也最高
 
InnoDB存储引擎既支持行级锁,也支持表级锁,但默认情况下是采用行级锁。

页级锁

一次锁定相邻的一组记录。开销和加锁时间介于表级锁和行级锁之间;会出现死锁;锁定粒度也介于表级锁和行级锁之间,并发度一般。

7.3 按使用机制划分,可分为乐观锁、悲观锁

悲观锁(Pessimistic Lock)

当要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制【Pessimistic Concurrency Control,缩写“PCC”,又名“悲观锁”】
 
悲观锁,具有强烈的独占和排他特性。它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度。因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

乐观锁(Optimistic Lock)

乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。

 


喜欢就一键三连支持下哩!
如果有错误的地方欢迎指出~😙
转载请标明:
https://blog.csdn.net/vihem/article/details/120983965

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/350725.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

004-从零搭建微服务-认证中心(四)

写在最前 如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。 源码地址:https://gitee.com/csps/mingyue 文档地址:https://gitee.com/csps/mingyue/wikis 搭建前端框架 感谢开源项目【vue-next-adm…

5年软件测试工程师工作感悟,谁还能“点点点”一辈子呢?

经常都有人问我软件测试前景怎么样,每年也都帮助很多朋友做职业分析和学习规划,也很欣慰能够通过自己的努力帮到一些人进入到大厂。 2023年软件测试行业的发展现状以及未来的前景趋势 最近很多测试人在找工作的时候,明显的会发现功能测试很…

【深入浅出 Spring Security(六)】一文搞懂密码的加密和比对

Spring Security 中的密码加密 一、PasswordEncoder 详解常见的实现类(了解)DelegatingPasswordEncoder源码分析DelegatingPasswordEncoder 在哪实例化的? 二、自定义加密自定义方式一:使用{id}的形式自定义方式二:向S…

花3个月面过阿里测开岗,拿个25K不过分吧?

计算机专业,代码能力一般,之前有过两段实习以及一个学校项目经历。第一份实习是大二暑期在深圳的一家互联网公司做前端开发,第二份实习由于大三暑假回国的时间比较短(小于两个月),于是找的实习是在一家初创…

Excel集成GPT,惊呆我了

Excel&GPT 从最开始的GPT对话,到后面的Office集成GPT进行内测,用GPT实现写Word、做Excel、做PPT(别着急,后面我会分享AIPPT)已经不再是设想,而在逐步演变成真的! 当然,目前国内…

impala内存超限

目录 一、背景 二、报错内容 三、解决办法 1.调参 2.简单粗暴 一、背景 impala shell执行SQL语句时报错 二、报错内容 Memory limit exceeded: Could not allocate memory while trying to increase reservation. 三、解决办法 1.调参 mem_limit参数:&…

2023,智能硬件的AIGC“又一春”

​ 文|智能相对论 作者|佘凯文 消费电子产品风光不再,特别是自去年以来,电子消费市场经历了一整年的寒潮袭击,智能手机等产品达到10年消费谷底,PC出货量整体下降16%,不仅如此,包括平板、可穿戴设备也一改…

Java读取U盘的PID、VID、SN

Java是不能像C、C那样直接读取U盘的PID、VID、SN信息的,但是我们可以换一个思路,让Java从注册表中读取信息。 这是U盘信息在注册表中的位置:HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\USBSTOR\\Enum import java.io.Buffer…

02_搭建项目(servlet+java bean+jsp的商城教程)

搭建项目 数据库和表项目包结构jar包工具类和配置文件前台文件(html,css,js,img等静态资源) 1)数据库和表 新建数据库store,按照上一节分析的实体结构创建数据表并插入数据: user表: CREATE TABLE user …

org.apache.jasper.JasperException: Unable to compile class for JSP

博主最近在将一个项目导入一台新机器的时候,出现了如题所述的异常,以前从没有出现过,我跟往常一样到网上寻求帮助,网上的解决方案多如牛毛,什么Tomcat版本与IDE不匹配、jar包冲突、xml文件错误、路径错误等等。在一一尝…

Java毕业设计:基于jsp+mysql+Spring+SpringMVC+mybatis的网络硬硬盘系統网站

项目介绍 网盘,又称网络U盘、网络硬盘,是一些网络公司推出的在线存储服务。向用户提供文件的存储、访问、备份、共享等文件管理功能,使用起来十分方便。不花钱的移动硬盘。用户可以把网盘看成一个放在网络上的硬盘或U盘,不管你是…

基于jsp+mysql+ssm网络硬硬盘系統网站-计算机毕业设计

项目介绍 网盘,又称网络U盘、网络硬盘,是一些网络公司推出的在线存储服务。向用户提供文件的存储、访问、备份、共享等文件管理功能,使用起来十分方便。不花钱的移动硬盘。用户可以把网盘看成一个放在网络上的硬盘或U盘,不管你是…

supermicro服务器通过U盘安装部署vmware vsphere并使用

制作U盘安装镜像 前提准备: 镜像: https://my.vmware.com/en/web/vmware/evalcenter?pfree-esxi6 直接到官网下载 VMware vSphere Hypervisor 6.7,不过要先注册才能用。另外这个是免费版的,有验证码,可以长期使用…

linux redhat9 u盘,LINUX(redhat9)下安装JDK(虚拟机VM上挂载U盘)

LINUX(redhat9)下安装JDK(虚拟机VM上挂载U盘) 2010-07-11 21:24 1.首先,我们去http://www.doczj.com/doc/11c2bbedb8f67c1cfad6b82a.html去下载JDK1.6.0 for LINUX的rpm. (http://www.doczj.com/doc/11c2bbedb8f67c1cfad6b82a.html/javase/downloads/index.jsp) 应该…

Ubuntu的JSP服务器安装

2019独角兽企业重金招聘Python工程师标准>>> 一、man中文版 1、安装:sudo apt-get install manpages-zh 2、把中文man包转换成utf8格式的 新建一个脚本文件gedit t.sh把下面内容添加进去#!/bin/bash cd /usr/share/man/zh_CN/ for k in *do cd $k for i …

JSP环境配置全解!

实现JSP文件环境配置除了MyEclipse外,最通俗的还是jdk加Tomcat。 今天上午刚把期末考试搞定,就紧迫不及待的在李超和超哥的指导下完成了JSP环境配置。以后要专心搞JAVA了,呵呵。。。 为了让我以后可以快速的独立配置环境…

关于电脑格式化之后的恢复

前言:在这里并没有用OneDrive备份的文件,为了极致的纯净,但是为了恢复基础资源的速度,建议用U盘或者百度云把TomCat和javeEE的文件夹上传一下,省的后面网站下的太慢 1.格式化电脑 桌面右键——》显示设置——》Window…

亚马逊云科技出海日倒计时,潮向新世界,亮点抢先知

数字化浪潮之下,中国企业的全球化步伐明显提速。从“借帆出海”到“生而全球化”,中国企业实现了从传统制造业“中国产品”出口,向创新“中国技术”和先导“中国品牌”的逐步升级。 作为全球云计算的开创者与引领者,亚马逊云科技…

使用jsp完成商品列表的动态显示

1数据库准备工作 1创建数据库 2 创建product表 代码如下: CREATE TABLE product (pid varchar(50) NOT NULL,pname varchar(50) DEFAULT NULL,market_price double DEFAULT NULL,shop_price double DEFAULT NULL,pimage varchar(200) DEFAULT NULL,pdate date DEFAU…

基于JSP的网络硬盘

1 可行性分析 web开发技术是Internet应用的一个重要方而,而JSP又是web开发的最先进的技术,是当前web开发人员的首选技术。 随着网络技术的日益普及和信息化建设的重视,网络硬盘是一种新型安全的网络存储系统,已越来越受到.人们的重…