【事务的特性及如何处理并发问题】

事务是一系列操作的集合,具有原子性、一致性、隔离性和持久性。MySQL默认隔离级别为Repeatable Read,可防止不可重复读,但无法解决幻读问题。设置隔离级别为Serializable可避免幻读,但可能引发串行化冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事务

事务简介

事务就是一系列操作的集合,它们之间不可分割。
事务会将一系列操作当做一个整体执行,要么全部成功,要么全部失败。
比较典型的例子就是银行转账系统,A给B转账,A账号减少一定金额,则B账号会增加一定金额。

注:在MySQL中事物的提交是自动的。也就是当我们执行一条语句后就直接提交了事务

事务操作

注:对于每一条SQL语句都可以看做是一个事务

#查看事务提交方式
#默认查询的结果为1,也就是自动提交事务
select @@autocommit;

#设置事务提交方式

##方式一
##将事务设置为手动提交
set @@autocommit = 0;

##方式二
###出现以下关键字就意味着需要手动提交事务
start transation;

#提交事务
commit;

#回滚事务
rollback;

在这里插入图片描述

#方式一实现

将MySQL中的事务设置为手动提交

set @@autocommit = 0;

#转账操作

#begin
##查询张三的余额
select * from account where name = '张三';

## 将张三的余额-1000
update account set money = money - 1000 where name = '张三';

...

##将李四的余额+1000
update account set money = money + 1000 where name = '李四';

#end

commit ;

#如果整个事务发生错误,执行回滚即可返回此次异常的事务操作,但前提是需要将事务的提交模式改为手动
rollback ;

注:

  1. 在编写错误的SQL语句时,最好设置为…,此时可视化工具才可判断出此语句有误。
  2. 在执行整个事务时,需要选中整个完整的事务代码执行
#方式二实现

start transaction;

-- 转账操作 (张三给李四转账1000)
-- 1. 查询张三账户余额
select * from account where name = '张三';

-- 2. 将张三账户余额-1000
update account set money = money - 1000 where name = '张三';

...

-- 3. 将李四账户余额+1000
update account set money = money + 1000 where name = '李四';

commit;

rollback ;

事务的四大特性(acid特性)

  1. 原子性(A):要么全部成功,要么全部失败
  2. 一致性(C):无论事务正常还是异常执行,所有的数据都会保持一致。如上述的张三和李四的金额加起来是一个恒定的值。
  3. 隔离性(I):可以在并发操作数据库的情况下独立运行。即两个事务之间的操作不互相影响,都可以独立运行。
  4. 持久性(D):事务一旦提交或回滚,对数据库的操作都是不可逆的。因为数据库中的数据最终存储在磁盘中

数据库中的数据存储的数据存储在电脑磁盘中,以下是test数据库中的四张表
在这里插入图片描述

事务隔离级别

隔离级别概述

在这里插入图片描述

查看和设置隔离级别

#查看事务隔离级别,默认情况下为 Repeatable Read
select @@transaction_isolation;

#设置隔离级别,session是仅设置当前会话的事务,global是设置全局会话的事务
set [session | gloabl] transaction isolation level  [ read uncommitted | read committed | repeatable read | serializable]

注:

  1. 事务的隔离级别越高,安全性就越高,但性能越低
  2. 事务的隔离级别是为了解决并发事务引起的问题
  3. MySQL的默认事务隔离级别是Repeatable Read

并发事务问题

在这里插入图片描述

脏读

事务A读取到事务B修改了但还未提交的数据。如下图中 右边的事务修改但未提交数据,而左边事务能访问到未提交的数据。

#事务的默认隔离级别是Repeatable Read,此级别不允许 脏读 问题
#所以需要将当前会话的事务隔离级别设置为 read uncommitted
 set session transaction isolation level read uncommitted;

在这里插入图片描述

注:如果想用使用某一数据库,一定要先使用 use 数据库定位到需要使用的数据库上

#将事务隔离等级设置为read committed则不可再读取为提交的数据。只有B事务提交了事务,A事务才能查看到修改后的事务。
set session transaction isolation level read committed;

在这里插入图片描述

不可重复读

默认情况下,MySQL的事务隔离等级设置为repeatable read,所以此时不需要设置事务的隔离等级。从下图可看出,即使事务B提交了修改的数据,但在A事务中的第二次查询仍和第一次的查询结果相同。故repeatable read隔离等级可以解决不可重复读问题。

在这里插入图片描述

幻读

默认情况的事务隔离等级不能解决幻读问题,如下图所示。事务A在第一次查询数据时没有id = 3的数据,而此时B事务插入 id = 3的记录并提交,当A事务也想插入 id = 3的记录时,则提示主键重复,但在进行第二次查询时还是查询不到 id = 3的数据。在A事务中的数据库中不能插入此条重复记录但又查询不到该记录。
在这里插入图片描述

此时就需要将事务隔离等级设置为serializable 。

set session transaction isolation level  serializable ;

此时B事务执行插入语句时就会被阻塞(执行插入语句后一直出现光标闪烁),直到A事务提交事务后B事务才可操作。
在这里插入图片描述

注:串行化就是指在并发环境下,一次只允许一个事务操作数据库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值