内部网站搭建,网店代运营的套路,html代码app,施工企业机械承包责任制度有道无术#xff0c;术尚可求#xff0c;有术无道#xff0c;止于术。 本系列Spring Boot 版本 3.1.0 本系列Seata 版本 2.0.0 源码地址#xff1a;https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 概述2. ACID 模型2.1 原子性2.2 一致性2.3 隔离性2… 有道无术术尚可求有术无道止于术。 本系列Spring Boot 版本 3.1.0 本系列Seata 版本 2.0.0 源码地址https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 概述2. ACID 模型2.1 原子性2.2 一致性2.3 隔离性2.3.1 事务并发异常2.3.1.1 第一类更新丢失回滚丢失2.3.1.2 第二类更新丢失覆盖丢失2.3.1.3 脏读2.3.1.4 不可重复读2.3.1.5 幻读 2.3.2 隔离级别2.3.2.1 读未提交 Read uncommitted2.3.2.2 读已提交 Read committed2.3.2.3 可重复度 Repeatable read2.3.2.4 序列化 Serializable 2.4 持久性 1. 概述
在计算机术语中事务Transaction是指多个数据库操作组成一个不可分割的执行单元这些操作要么全部成功要么全部失败不会结束在中间的某个环节同时在这些操作执行后需要保证数据可靠且一致。
例如在MySql中使用事务
-- 开启事务
START TRANSACTION;
-- 一些列操作
INSERT INTO user(username,password) VALUES (root,123456); -- 插入
UPDATE t_user SET username’cangJJ’ WHERE id1; -- 更新-- 提交事务
COMMIT;2. ACID 模型
ACID模型是指数据库中的事务必须满足原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability四大特性是数据库设计的基本原则以保证数据的可靠一致即便在软件崩溃、硬件故障的情况下数据也不会被破坏。
其中原子性、隔离性、持久性是为一致性服务的即AID是手段C是最终实现的目标。
2.1 原子性
原子性也可称为不可分割性是说事务操作必须是原子工作单元一个事务中的操作要么全部都执行成功要么全部都回滚撤销执行不会存在部分成功或失败的情况。
例如经典的银行转账场景中转账操作可以分为以下两步
从A账户中扣除金额将扣除金额存入到B账户 整个转账操作过程可以看作是一个事务原子性要求成功则全部成功失败则需要全部撤消。如果第一步成功第二步失败整个操作应该取消若不取消第一步的操作则会发生丢失款项的问题。
2.2 一致性
一致性是指一个事务执行之前和执行之后都必须处于一致性状态。
2.3 隔离性
隔离性是指当多个用户并发访问数据库时比如操作同一张表时数据库为每一个用户开启的事务不能被其他事务的操作所干扰多个并发事务之间要相互隔离。
2.3.1 事务并发异常
数据库是要被共享访问的那么在并发操作数据库过程中很可能出现以下很多异常情况。
2.3.1.1 第一类更新丢失回滚丢失
比如下图中T1、T2同时执行由于没有事务隔离虽然T1更新成功但是T2进行了回滚余额却没有变化这种因为回滚导致另外一个事务操作丢失的情况叫做回滚丢失。
2.3.1.2 第二类更新丢失覆盖丢失
比如下图中T1、T2同时执行由于没有事务隔离T1、T2都提交了事务但是由于T2后执行将T1事务的操作覆盖了导致更新丢失问题。
2.3.1.3 脏读
脏读是因为一个事务读取了另一个事务修改了但是未提交的数据。
比如下图中T1修改余额为1100此时T2开始事务查询到的结果为1100由于读取到了未提交的事务当T1回滚时T2还在脏数据上操作会导致结果错误。
2.3.1.4 不可重复读
不可重复读是指一个事务对同一行数据执行了两次或更多次查询但是却得到了不同的结果。
比如下图中在T2中多次查询的不一致如果这个时候修改就会造成数据错误。 2.3.1.5 幻读
幻读和不可重复读有点像两者都表现为两次读取的结果不一致只是针对的不是数据的值而是数据的数量。不可重复读重点在于update和delete而幻读的重点在于insert。
如果使用锁机制来实现这两种隔离级别在可重复读中该sql第一次读取到数据后就将这些数据加锁其它事务无法修改这些数据就可以实现可重复读了。但这种方法却无法锁住insert的数据所以当事务A先前读取了数据或者修改了全部数据事务B还是可以insert数据提交这时事务A就会 发现莫名其妙多了一条之前没有的数据这就是幻读不能通过行锁来避免。
2.3.2 隔离级别
数据并发访问所产生的问题在有些场景下可能是允许的但是有些场景下可能就是致命的数据库通常会通过锁机制来解决数据并发访问问题
直接使用锁是非常麻烦的为此数据库为用户提供了自动锁机制只要用户指定会话的事务隔离级别数据库就会通过分析SQL语句然后为事务访问的资源加上合适的锁此外数据库还会维护这些锁通过各种手段提高系统的性能这些对用户来说都是透明的。ANSI/ISO SQL 92标准定义了4个等级的事务隔离级别如下表所示 事务隔离级别和数据访问的并发性是对立的事务隔离级别越高并发性就越差。所以要根据具体的应用来确定合适的事务隔离级别这个地方没有万能的原则。
可以通过以下SQL 查询和修改会话级别
-- 查询数据库版本
SELECT VERSION();
-- 查询当前会话事务界别
SELECT session.tx_isolation;
-- 设置当前会话事务隔离级别仅仅该窗口会话有效
set session tx_isolationread-uncommitted;2.3.2.1 读未提交 Read uncommitted
读未提交顾名思义就是一个事务可以读取另一个未提交事务的数据这个级别几乎没有任何隔离性一般不会采用这个隔离级别。
2.3.2.2 读已提交 Read committed
读提交顾名思义就是一个事务要等另一个事务提交后才能读取数据。另外一个事务不能读取该事务未提交的数据。
在Navicat 中打开两个会话窗口修改隔离级别为读已提交
-- 设置当前会话事务隔离级别仅仅该窗口会话有效
set session tx_isolationRead-committed;开启事务将当前账户余额扣掉100不提交事务
START TRANSACTION;
UPDATE account_tbl
SET money money - 100
WHEREid 11111111;在另外一个窗口查询当余额
SELECT*
FROMaccount_tbl
WHEREid 11111111;可以看到读取到的余额仍为1000说明该隔离级别下事务读取不到另外一个事务未提交的数据。
分析这就是读已提交若有事务对数据进行更新UPDATE操作时读操作事务要等待这个更新操作事务提交后才能读取数据可以解决脏读问题。但是存在不可重复读问题一旦事务提交后另外的事务再次查询查询结果会不一致。
2.3.2.3 可重复度 Repeatable read
可重复读就是在开始读取数据事务开启时多次读取到的结果是一致的这是Mysql 默认的事务隔离级别。
比如我们先开启一个事务读取数据此时查询结果为1000 另外一个事务修改当前数据并提交事务 查询事务中再次查询发现余额没有变这就是可重复读Repeatable Read的确可以解决“不可重复读”的问题。
2.3.2.4 序列化 Serializable
Serializable是最严格的隔离级别。在Serializable隔离级别下所有事务按照次序依次执行因此脏读、不可重复读、幻读都不会出现。
虽然Serializable隔离级别下的事务具有最高的安全性但是由于事务是串行执行所以效率会大大下降应用程序的性能会急剧降低。如果没有特别重要的情景一般都不会使用Serializable隔离级别。
2.4 持久性
持久性是指事务一旦被提交对数据库中的数据的改变就是永久性的不会因为任何情况回到原来的状态。