一起来学MySQL—事务的隔离级别
发布日期:2021-06-29 11:14:50 浏览次数:2 分类:技术文章

本文共 2452 字,大约阅读时间需要 8 分钟。

事务的含义

事务:一条或多条 sql 语句组成的一个执行单元,这组 sql 语句是一个整体,要么都顺利执行,要么都不执行,只要在执行的过程中,有一条 sql 语句执行错误就全部回滚或部分回滚。

事务的特性

事务总共有 4 大特性:ACID。

A(Atomicity)原子性:一个事务是不可再分割的整体,要么都执行要么都不执行

C(Consistency)一致性:一个事务可以使数据从一个一致状态切换到另外一个一致的状态。比如 A 和 B 的账户上都各有 1000 元,在 A 给 B 转了 500 元之后,A 的账户上 是 500 元,B 的账户上是 1500 元,两人的总额还是 2000 元。

I(Isolation)隔离性:一个事务不受其他事务的干扰,多个事务互相隔离

D(Durability)持久性:一个事务一旦提交了,则它对数据库中数据的改变就是永久性的

事务的使用步骤

首先事务分为两类:一种是隐式事务,一种是显式事务。

像单条的 insert、update、delete 语句,本身都是一条事务,只不过由 MySQL 自动提交了。
而显式事务则需要我们自己手动的提交或回滚。

使用显式事务的步骤:

① 首先要开启事务,将自动提交关闭。

set autocommit = 0;start transaction;  #可以省略

② 编写一组 sql 语句,在其间可以设置会滚点。

savepoint 回滚点名;    #设置回滚点`

③ 结束事务

  提交:commit;
  回滚:rollback;
  回滚到指定的地方:rollback to 回滚点名;

演示 savepoint 的使用:

SET autocommit = 0;START TRANSACTION;DELETE FROM account WHERE id=25;SAVEPOINT a;#设置保存点DELETE FROM account WHERE id=28;ROLLBACK TO a;#回滚到保存点

事务的并发问题

当多个事务同时操作同一个数据库的相同数据时,就会出现事务的并发问题。

那事务的并发问题都有哪些呢?

  • 脏读: 对于两个事务 T1, T2。T1 读取了已经被 T2 更新但还没有被提交的字段。之后,若 T2 回滚,则 T1 读取的内容就是临时且无效的。
  • 不可重复读:对于两个事务T1, T2。T1 读取了一个字段,然后 T2 更新了该字段。之后,T1再次读取同一个字段,值就不同了。
  • 幻读:对于两个事务T1, T2。T1 从一个表中读取所有的数据行, 然后 T2 在该表中插入了一些新的行。之后, 如果 T1 更改表中所有的数据时,就会发现多修改了几行,返回的行数不是之前的总行数。

事务的隔离级别

对于事务的并发问题,我们可以通过设置不同的隔离级别来解决这些并发问题。

MySQL 支持 4 种隔离级别:

隔离级别 描述
READ UNCOMMITTED(读未提交数据) 允许事务读取未被其他事务提交的变更脏读,不可重复读和幻读的问题都会出现
READ COMMITTED(读已提交数据) 只允许事务读取已经被其它事务提交的变更。可以避免脏读,但不可重复读和幻读问题仍然可能出现
REPEATABLE READ(可重复读) 确保事务可以多次从一个字段中读取相同的值。可以避免脏读和不可重复读,但幻读的问题仍然存在。
SERIALIZABLE(串行化) 确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入,更新和删除操作,所有并发问题都可以避免,但性能十分低下

隔离级别越高, 数据一致性就越好, 但并发性越弱。

补充:

 Oracle 支持 2 种事务隔离级别:READ COMMITED 和 SERIALIZABLE。Oracle 默认的事务隔离级别为: READCOMMITED。
 Mysql 默认的事务隔离级别为: REPEATABLE READ。

事务并发问题的演示

每启动一个 mysql 程序, 就会获得一个单独的数据库连接。每个数据库连接都有一个全局变量 @@tx_isolation, 表示当前的事务隔离级别。

查看当前的隔离级别: SELECT @@tx_isolation;

设置当前 MySQL 连接的隔离级别:set session transaction isolation level read committed;
设置数据库系统的全局的隔离级别:set global transaction isolation level read committed;

1、先创建一个表 account,往里面插入 2 条数据

CREATE TABLE `account` (  `id` int PRIMARY KEY AUTO_INCREMENT,  `username` varchar(20) ,  `balance` int ,);INSERT INTO account(username,balance) VALUES('刘备',1000),('关羽',1000);

2、开启两个 MySQL 连接,首先设置数据库的隔离级别为:read uncommitted;,演示出现的问题。

在这里插入图片描述
3、修改数据库的隔离级别为:read committed,解决了脏读的问题,但是会出现不可重复读的问题。
在这里插入图片描述
4、修改数据库的隔离级别为:repeatable read,解决了脏读和不可重复读的问题,但是会出现幻读。
在这里插入图片描述
5、修改数据库的隔离级别为:serializable,脏读、不可重复读、幻读的问题都解决了。
在这里插入图片描述
最后,总结一下,不同的隔离级别都能解决什么问题:

脏读 不可重复读 幻读
READ UNCOMMITTED × × ×
READ COMMITTED × ×
REPEATABLE READ ×
SERIALIZABLE

转载地址:https://blog.csdn.net/zwj_jyzl/article/details/106951353 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Spring 核心 之 AOP
下一篇:Spring 核心 之 IOC

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年04月27日 10时21分49秒