事务及四大特性

1 什么是事务

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

简单的说:事务就是将一堆SQL(通常是增删改操作)的执行绑在一起,要么都执行成功,要么都执行失败,即都执行成功才算成功,否则就会恢复到这堆SQL执行之前的状态。

下面以银行转账为例,张三转100块到李四的账户,这至少需要两条SQL语句:

l 给张三的账户减去100元;

update 账户表 set money=money-100 where name=‘张三’;

l 给李四的账户加上100元。

update 账户表 set money=money+100 where name=‘李四’;

如果在第一条SQL语句执行成功后,在执行第二条SQL语句之前,程序被中断了(可能是抛出了某个异常,也可能是其他什么原因),那么李四的账户没有加上100元,而张三却减去了100元。这肯定是不行的。

你现在可能已经知道什么是事务了吧!在上面整个转账过程中执行的所有SQL语句会在一个事务中,而事务中的多个操作,要么全都成功,要么全都失败,不可能存在成功一半的情况。

也就是说给张三的账户减去100元如果成功了,那么给李四的账户加上100元的操作也必须是成功的;否则,给张三减去100元以及给李四加上100元都是失败的。

2 事务的四大特性

事务的四大特性(ACID)是:

(1)原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。

(2)一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号金额之和应该是不变的。

(3)隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。也就是说,在事中务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。例如:在A事务中,查看另一B事务(正在修改张三的账户金额)中张三的账户金额,要查看到B事务之前的张三的账户金额,要么查看到B事务之后张三的账户金额。

(4)持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。

3 MySQL中的事务

查看当前自动提交功能状况:
show variables like ‘autocommit’;
±--------------±------+
| Variable_name | Value |
±--------------±------+
| autocommit | ON |
±--------------±------+
1 row in set (0.06 sec)

临时生效设置方法:
下面是将自动提交功能置为ON以及置为OFF的具体语法。
将自动提交功能置为ON
SET AUTOCOMMIT=1;

将自动提交功能置为OFF
SET AUTOCOMMIT=0;

永久生效设置方法:
通过修改配置文件my.cnf文件,通过vim编辑my.cnf文件,在[mysqld](服务器选项下)添加:
autocommit=0

在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。

l 开启事务:start transaction;

l 结束事务:commit(提交事务)或rollback(回滚事务)。

在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,最后要结束事务,commit表示提交,即事务中的多条SQL语句所做出的影响会持久化到数据库中。或者rollback,表示回滚,即回滚到事务的起点,之前做的所有操作都被撤消了!

下面演示A账户给B账户转账的例子:

** 准备数据:-- 1、创建数据库jt_db数据库(如果不存在才创建)
create database if not exists jt_db charset utf8;
use jt_db; -- 选择jt_db数据库-- 2、在 jt_db 库中创建 acc 表(银行账户表), 要求有id(主键),name(姓名),money(账户金额)
drop table if exists acc;
create table acc(id int primary key auto_increment,name varchar(50),money double
);-- 3、往 acc 表中, 插入2条记录
insert into acc values(null,'A',1000);
insert into acc values(null,'B',1000);-- 查询acc表中的所有记录
select * from acc;下面分别演示事务开启及执行一系列SQL之后,回滚事务、提交事务及中断操作的效果。
rollback(回滚事务):-- 查询acc账户表中A和B的金额
select * from acc;-- 开启事务
start transaction;-- 开始转账,A账户减去100元
update acc set money=money-100 where name='A';-- 查询acc账户表中A和B的金额
select * from acc;-- B账户增加100元
update acc set money=money+100 where name='B';-- 查询acc账户表中A和B的金额
select * from acc;-- 回滚事务
rollback;-- 再次查询acc账户表中A和B的金额
select * from acc;commit(提交事务):
-- 将上面的操作再做一次,最后将rollback替换为commit,即提交事务
commit;中断操作
-- 将上面的操作再做一次,最后将rollback替换为quit,即中断操作
quit;

事务并发读问题

1 事务并发读问题

多个事务对相同的数据同时进行操作,这叫做事务并发。

在事务并发时,如果没有采取必要的隔离措施,可能会导致各种并发问题,破坏数据的完整性等。这些问题中,其中有三类是读问题,分别是:脏读、不可重复读、幻读。

(1)脏读(dirty read):读到另一个事务的未提交更新数据,即读取到了脏数据;

例如:A给B转账100元但未提交事务,在B查询后,A做了回滚操作,那么B查询到了A未提交的数据,就称之为脏读。

(2)不可重复读(unrepeatable read):对同一记录的两次读取不一致,因为另一事务对该记录做了修改(是针对修改操作)

例如:在事务1中,前后两次查询A账户的金额,在两次查询之间,另一事物2对A账户的金额做了修改,此种情况可能会导致事务1中,前后两次查询的结果不一致。这就是不可重复度

(3)幻读(虚读)(phantom read):对同一张表的两次查询不一致,因为另一事务插入了一条记录(是针对插入或删除操作);

注意:mysql默认的是不允许出现脏读和不可重复读,所以在下面演示之前需要设置mysql允许出现脏读、不可重复读等。

set tx_isolation=‘read-uncommitted’;

脏读示例:

-- 在窗口1中,开启事务,执行A给B转账100元
set tx_isolation='read-uncommitted'; -- 允许脏读、不可重复读、幻读
use jt_db; -- 选择jt_db库
start transaction; -- 开启事务
update acc set money=money-100 where name='A';
update acc set money=money+100 where name='B';-- 在窗口2中,开启事务,查询B的账户金额
set tx_isolation='read-uncommitted'; -- 允许脏读、不可重复读、幻读
use jt_db; -- 选择jt_db库
start transaction; -- 开启事务
select * from acc where name='B'; -- 出现脏数据-- 切换到窗口1,回滚事务,撤销转账操作。
rollback; -- 回滚事务-- 切换到窗口2,查询B的账户金额
select * from acc where name='B';

在窗口2中,B看到自己的账户增加了100元(此时的数据A操作事务并未提交),此种情况称之为"脏读"。

不可重复读示例:

-- 在窗口1中,开启事务,查询A账户的金额
set tx_isolation='read-uncommitted'; -- 允许脏读、不可重复读、幻读
use jt_db; -- 选择jt_db库
start transaction; -- 开启事务
select * from acc where name='A';-- 在窗口2中,开启事务,查询A的账户金额减100
set tx_isolation='read-uncommitted'; -- 允许脏读、不可重复读、幻读
use jt_db; -- 选择jt_db库
start transaction; -- 开启事务
update acc set money=money-100 where name='A'; -- A账户减去100
select * from acc where name='A';
commit; -- 提交事务-- 切换到窗口1,再次查询A账户的金额。
select * from acc where name='A'; -- 前后查询结果不一致

在窗口1中,前后两次对同一数据(账户A的金额)查询结果不一致,是因为在两次查询之间,另一事务对A账户的金额做了修改。此种情况就是"不可以重复读"

幻读示例:

-- 在窗口1中,开启事务,查询账户表中是否存在id=3的账户
set tx_isolation='read-uncommitted'; -- 允许脏读、不可重复读、幻读
use jt_db; -- 选择jt_db库
start transaction; -- 开启事务
select * from acc where id=3;-- 在窗口2中,开启事务,往账户表中插入了一条id为3记录,并提交事务。
-- 设置mysql允许出现脏读、不可重复度、幻读
set tx_isolation='read-uncommitted';
use jt_db; -- 选择jt_db库
start transaction; -- 开启事务
insert into acc values(3, 'C', 1000);
commit; -- 提交事务-- 切换到窗口1,由于上面窗口1中查询到没有id为3的记录,所以可以插入id为3的记录。
insert into acc values(3, 'C', 1000); -- 插入会失败!

在窗口1中,查询了不存在id为3的记录,所以接下来要执行插入id为3的记录,但是还未执行插入时,另一事务中插入了id为3的记录并提交了事务,所以接下来窗口1中执行插入操作会失败。

探究原因,发现账户表中又有了id为3的记录(感觉像是出现了幻觉)。这种情况称之为"幻读"

以上就是在事务并发时常见的三种并发读问题,那么如何防止这些问题的产生?

可以通过设置事务隔离级别进行预防。

2 事务隔离级别

事务隔离级别分四个等级,在相同数据环境下,对数据执行相同的操作,设置不同的隔离级别,可能导致不同的结果。不同事务隔离级别能够解决的数据并发问题的能力也是不同的。

set tx_isolation=‘read-uncommitted’;

1、READ UNCOMMITTED(读未提交数据)

安全级别最低, 可能出现任何事务并发问题(比如脏读、不可以重复读、幻读等)

性能最好(不使用!!)

2、READ COMMITTED(读已提交数据)(Oracle默认)

防止脏读,没有处理不可重复读,也没有处理幻读;

性能比REPEATABLE READ好

3、REPEATABLE READ(可重复读)(MySQL默认)

防止脏读不可重复读,不能处理幻读问题;

性能比SERIALIZABLE好

4、SERIALIZABLE(串行化)

不会出现任何并发问题,因为它是对同一数据的访问是串行的,非并发访问的;

性能最差;

MySQL的默认隔离级别为REPEATABLE READ,即可以防止脏读和不可重复读

3 设置隔离级别

0、MySQL查询当前的事务隔离级别

select @@tx_isolation;

1、MySQL设置事务隔离级别(了解)

(1) set tx_isolation=‘read-uncommitted’;

安全性最差,容易出现脏读不可重复读幻觉读,但性能最高

(2) set tx_isolation=‘read-committed’;

安全性一般,可防止脏读,但容易出现不可重复读幻觉读

(3) set tx_isolation=‘repeatable-read’;

安全性较好,可防止脏读不可重复读,但是容易出现幻读

(4) set tx_isolation=‘serialiable’;

安全性最好,可以防止一切事务并发问题,但是性能最差。

2、JDBC设置事务隔离界别

JDBC中通过Connection提供的方法设置事务隔离级别:

Connection. setTransactionIsolation(int level)

参数可选值如下:

Connection.TRANSACTION_READ_UNCOMMITTED 1(读未提交数据)

Connection.TRANSACTION_READ_COMMITTED 2(读已提交数据)

Connection.TRANSACTION_REPEATABLE_READ 4(可重复读)

Connection.TRANSACTION_SERIALIZABLE 8(串行化)

Connection.TRANSACTION_NONE 0(不使用事务)

提示:在开发中,一般情况下不需要修改事务隔离级别

数据库事务及四大特性相关推荐

  1. 数据库事务的四大特性ACID

    本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务 ...

  2. 数据库事务的四大特性以及隔离级别

    本篇文章主要介绍数据库事务的四大特性ACID,以及数据库的隔离级别. 事务 概念 事务指的是满足 ACID 特性的一系列操作.在数据库中,可以通过 Commit提交一个事务,也可以使用 Rollbac ...

  3. 数据库事务及其四大特性

    数据库事务是数据库运行中的逻辑工作单位,单个逻辑工作单元所执行的一系列操作,要么都执行,要么都不执行.例如银行取款事务分为2个步骤(1)存折减款(2)提取现金,2个步骤必须同时完成或者都不完成. 数据 ...

  4. 数据库事务的四大特性和四个隔离级别

    一.数据库事务的四大特性 事物是指作为一个单元的一组有序的数据库操作,单元是不可分割的,如果一组数据的所有操作都执行成功,事物完成,进行事物提交(commit),其修改作用于所有数据库进程.有一个操作 ...

  5. MySQL数据库事务的四大特性

    MySQL数据库事务的四大特性以及事务的隔离级别_l1394049664的博客-CSDN博客_mysql数据库事务 深入学习MySQL事务:ACID特性的实现原理 - 编程迷思 - 博客园

  6. 数据库事务的四大特性(ACID)

    数据库事务的四大特性 1,      什么是数据库事务? 数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成. 意思就是一连串的数据库操作,即一串增删查改的集合. 2,   数据库 ...

  7. 数据库事务的四大特性和隔离级别

    数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么全部执行,要么全部都不执行. 一个逻辑工作单元要成为事务,必须满足事务的四大特性(ACID).即 ...

  8. 数据库事务的四大特性以及事务的隔离级别

    本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务 ...

  9. 数据库事务的四大特性以及事务的隔离级别详解

    作者 : fjdingsd 来源 : 博客园 本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ ...

  10. 数据库事务的四大特性及事务隔离级别

    概要: 事务的四个特性:原子性.一致性.隔离性.持久性 事务不隔离带来的问题:更新丢失.脏读.不可重复读.虚读(幻读).其中更新丢失就是并发写,这是一定不允许的,因此一定要解决更新丢失问题. 事务隔离 ...

最新文章

  1. JAVA IF判断语句
  2. java标识符与关键字_4、Java标识符和关键字
  3. Pytorch骨干网络性能测试
  4. Lombok的@Data生成的hashCode和equals方法坑
  5. 手机进程设置多少个最好_安卓手机难逃卡顿宿命?打开4个系统设置,秒变新机般流畅...
  6. 视觉SLAM-显示相机的位姿
  7. 计算机审计操作实验目的,计算机审计实验报告 满分原创!!.docx
  8. 应届生去软通动力怎么样_超强干货:应届生如何找实习工作?
  9. JavaWeb项目开发案例精粹-第6章报价管理系统-001需求分析及设计
  10. html选择同级的元素,jquery获取同级元素
  11. blender php,Blender 源码学习 --- Modifier
  12. Phpcms V9 栏目列表调用文章点击量及评论数量方法(转)
  13. python第一记,长江雨课堂抓包刷课实战
  14. 通过降低CPU频率 达到降低功耗的目的
  15. 智慧产业园区综合解决方案
  16. 虚拟互动展会沉浸式体验方案设计优势
  17. Spec2006使用说明
  18. SpringBoot 整合activiti5.22 实现一个完整的请假流程
  19. 数字图像处理——形态学操作(二值图像篇)
  20. windows系统安装时转换硬盘格式为NTFS

热门文章

  1. silk lobe资源公众号_电视剧资源免费看公众号【推荐】
  2. 什么是 MySQL 索引?
  3. rk3128 平台rk818电源管理驱动移植
  4. Adjoint of SE(3)
  5. linux解决用户权限不够问题
  6. 数据库出错提示Duplicate entry * for key *的解决方法
  7. iphone html复制粘贴,教大家如何在iPhone上复制内容快速粘贴到iPad上
  8. System进程下vibran_drv.sys CPU占用率高
  9. Kubernetes30--弹性伸缩总结
  10. Web前端工程师工资逐年增长,背后有哪些因素?