MySQL事务

1.什么是事务?

事务(Transaction)是将⼀组操作封装成⼀个执⾏单元(封装到⼀起),这⼀个执⾏单元要么⼀起执⾏ 成功,要么⼀起失败,不会出现执⾏“⼀半”的情况。
数据库引擎:InnoDB才支持事务,MyISAM不支持事务。

2.为什么⽤事务?

以银⾏转账为例,A 转账 B 转账,那么它的执⾏流程是这样的:
A 账户 -500
B 账户 +500
试想⼀下,如果执⾏了⼀半,断点了或者程序崩溃了,那么 A 账号的钱就永久消失了?那怎么办?⽤事 务就可以解决,封装成⼀个执⾏单元,要么⼀起成功,要么⼀起失败。
使⽤数据库演示⼀下,准备测试表:

create table account(
      id int primary key auto_increment,
      name varchar(20) comment '账户名称',
      money decimal(11,2) comment '⾦额');

 insert into account(name, money) values
     ('张三', 1000),
     ('李四', 1000);

张三给李四转 500 元,操作如下:

-- 操作1:张三账户减500
1.update account set money=money-500 where name='张三';
 -- 李四账户增加500
2.update account set money=money+500 where name = '李四';

假如在执⾏以上第⼀句 SQL 时,出现⽹络错误,或是数据库挂掉了,阿⾥巴巴的账户会减少 500,但是 李四的账户上就没有了增加的⾦额。

3.事务的使用?

3.1开启事务(start transaction)

MySQL8之前使用start transaction,MySQL8之后使用begin
转账业务(多条SQL)

3.2提交事务(commit)

commit

3.3回滚事务(rollback)

rollback
在这里插入图片描述
在这里插入图片描述
注意事项:
事务在开启之后,必须以提交事务或回滚事务来结束。如果没有提交事务或回滚事务来结束,那么修改是无效的

事务的四大特征(ACID)

事务有4 大特性(ACID),原子性(不可分割性):、一致性和隔离性(独立性)、持久性。
具体概念如下:

原子性(Atomicity):

一个事务中的所有操作,要么全部执行成功,要么全部执行失败。
原子性是事务最重要的特性,全部执行失败并不是不执行,而是通过逆操作 rollback(回滚)数据。
实现原理:回滚是逆 SQL 操作:比如 A 账户 -500 元的逆操作就是 A 账户 +500 元。

一致性(Consistency):

一个事务在执行前后数据必须保持一种合法的状态,事务总是从一个一致状态到另一个一致状态。
举例说明:比如转账操作,转账之前两个账号的总额是 100 元(各个 50 元),那么两个账户相互转账之后的钱总额也是 100 元,也就是事务总是从一个一致状态到另一个一致状态,不会说转账之前是100 元,相互转账之后变成 80 了,这就不符合一致性了。

持久性(Durability):

事务执行完成之后,它所做的所有修改都是永久的(不会丢失)。
数据存储到磁盘中就是持久的,不会丢失的,不会因为电脑重启而丢失。

隔离性(重要)(Isolation):

多个事务并发访问时,事务之间是相互隔离的,一个事务不应该被其他事务干扰,多个并发事务之间要相互隔离。
举例说明:比如宠物店,如果宠物店来了一个狗狗,那么是可以正常的处理它的诉求的,比如打个疫苗啊、美个容啊都是可以很顺利的完成的,但是如果一个 20 平方的宠物商店来了 20 只狗那它们就得打起来了,这个时候怎么办?把它们装到笼子里面“隔离”起来啊,这和咱们的事务的隔离性是一样的,都是解决多个事务同时请求的问题的。

MySQL 事务隔离级别有 4 种(重要)

1. READ UNCOMMITTED(读未提交)[脏读]

读未提交,也叫未提交读,该隔离级别的事务可以看到其他事务中未提交的数据。该隔离级别因为可以读取到其他事务中未提交的数据,而未提交的数据可能会发生回滚,因此我们把该级别读取到的数据称之为脏数据(幽灵数据),把这个问题称之为脏读

脏读

一个事务读取到了另一个事务修改的数据之后,后一个事务又进行了回滚操作,从而导致
第一个事务读取的数据是错误的。

2. READ COMMITTED(读已提交)[不可重复读]

读已提交,也叫提交读,该隔离级别的事务能读取到已经提交事务的数据,因此它不会有脏读问题。但由于在事务的执行中可以读取到其他事务提交的结果,所以在不同时间的相同 SQL 查询中,可能会得到不同的结果,这种现象叫做不可重复读

不可重复读

使用相同的SQL,得到了不同的结果,这个就叫做不可重复读。
在一个事务中,两次查询同一条数据得到了不同的结果就是不可重复读。在一个事务两次查询中间,另一个事务把这条数据修改了。

3. REPEATABLE READ(可重复读)[幻读]

可重复读,是 MySQL 的默认事务隔离级别,它能确保同一事务多次查询的结果一致。但也会有新的问题,比如此级别的事务正在执行时,另一个事务成功的插入了某条数据,但因为它每次查询的结果都是一样的,所以会导致查询不到这条数据,自己重复插入时又失败(因为唯一约束的原因)。明明在事务中查询不到这条信息,但自己就是插入不进去,这就叫幻读(Phantom Read)。
不可重复读的事务隔离可以解决不可重复读得问题,但存在幻读问题。
如果不存在幻读问题,那么无论你如何执行,都不会出现幻象行的,也就不会出现多一条数据的问题的(使用相同的SQL)

幻读

在同一事务的不同时间使用相同SQL查询时,会产生不同的结果。
当同一查询在不同时间产生不同的结果,就是事务中的幻读问题。例如,一个 SELECT 被
执行了两次,但是第二次返回了第一次没有返回的一行,那么这一行就是一个“幻像”行。

4. SERIALIZABLE(序列化)

序列化,事务最高隔离级别,它会强制事务排序,使之不会发生冲突,从而解决了脏读、不可重复读和幻读问题,但因为执行效率低,所以真正使用的场景并不多。

在这里插入图片描述

MySQL是支持给每个连接客户单独设置事务的隔离级别。

a)查询事务的隔离级别

语法:

select @@global.tx_isolation,@@global.tx_isolation;

在这里插入图片描述

b)设置当前客户端的事务隔离级别

语法:

set session transaction isolation level 隔离级别;

设置当前连接的事务隔离级别为读未提交:
在这里插入图片描述
结论:读未提交(read uncommitted)存在脏读的习惯

不可重复读和幻读有什么区别?

答:不可重复读和幻读描述的侧重点是不同的。
不可重复读描述的是修改操作,比如t1时间读取了一行数据,t2时间的时候读取到了这个数据,内容发生了改变,这个就叫做不可重复读。
而幻读描述的是幻象行的问题,它是指在t1时间使用SQL得到了n条数据,而在t3时间使用相同的SQL却得到了n+1条数据,那么多出来的这一行数据叫做幻象行,而这个操作就叫做幻读。
也就是说不可重复读描述的侧重点是修改操作,而幻读描述的侧重点是添加(或删除)操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值