2021年Java面经分享:MySQL-InnoDB-事务

ROLLBACK;

## 事务 ACID 特性

**原子性(Atomicity)**:最小的工作单元,整个工作单元要么一起提交成功,要么全部失败回滚。

**一致性(Consistency)**:事务中操作的数据及状态改变是一致的,即写入资料的结果必须完全符合预设的规则,不会因为出现系统意外等原因导致状态的不一致。

**隔离型(Isolation)**:一个事务所操作的数据在提交之前,对其他事务的可见性设定(一般设定为不可见)。

**持久性(Durability)**:事务所做的修改就会永久保存,不会因为系统意外导致数据的丢失。

## 事务并发带来了哪些问题

### 脏读

![](https://upload-images.jianshu.io/upload_images/13465705-022fa6856705ae65.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

比如 user 表中有一条用户数据,执行了如下操作:

1.  事务B更新 id=1 的数据,age 更新为18,不提交事务
2.  事务A查询 id=1 的数据
3.  事务B回滚刚才的更新操作

这个时候,事务A中查询出的 id=1 的数据,age 的值是16还是18?

### 不可重复读

![](https://upload-images.jianshu.io/upload_images/13465705-95d0d31c1e9ed121.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

比如 user 表中有一条用户数据,执行了如下操作:

1.  事务A查询 id=1 的数据
2.  事务B更新 id=1 的数据,age 更新为18,并提交事务
3.  事务A再次查询 id=1 的数据

这个时候,事务A两次查询出的 id=1 的数据,age 的值是16还是18?

### 幻读

![](https://upload-images.jianshu.io/upload_images/13465705-2e3417dd22d29174.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

比如在 user 表中执行了如下操作:

1.  事务A查询 age>15 的数据
2.  事务B新增一条数据,age=22,并提交事务
3.  事务A再次查询 age>15 的数据

这个时候,事务A两次查询出的数据,数量是1条还是2条?

## 事务四种隔离级别

**SQL92 ANSI/ISO标准**:http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

**Read Uncommitted(未提交读)** --**未解决并发问题**

事务未提交对其他事务也是可见的,脏读(dirty read)

**Read Committed(提交读)** --**解决脏读问题**

一个事务开始之后,只能看到自己提交的事务所做的修改,不可重复读(non repeatable read)

**Repeatable Read(可重复读)** --**解决不可重复读问题**

在同一个事务中多次读取同样的数据结果是一样的,这种隔离级别未定义解决幻读的问题

**Serializable(串行化)** --**解决所有问题**

最高的隔离级别,通过强制事务的串行执行

## InnoDB 引擎对隔离级别的支持程度

![](https://upload-images.jianshu.io/upload_images/13465705-d8cda5351f47e6db.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

事务隔离级别的并发能力:未提交读 > 已提交读 > 可重复读 > 串行化

InnDB 引擎默认的事务隔离级别是可重复读(Repeatable Read),在该级别中它把幻读的问题也解决了。InnDB 中事务隔离级别通过锁、MVCC 实现。

通过如下语句查看 InnoDB 的默认事务隔离级别:

/* 全局、当前会话的隔离级别 */
SELECT @@global.tx_isolation, @@tx_isolation;

![](https://upload-images.jianshu.io/upload_images/13465705-5d3119872514a339.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

通过如下语句设置 InnoDB 的事务隔离级别:

/* 设置全局隔离级别 /
set global transaction isolation level read committed;
/
设置当前会话的隔离级别 */
set session transaction isolation level read committed;

接下来我们来测试一下 InnoDB 的默认事务隔离级别(Repeatable Read)是否解决了脏读、不可重复读、幻读的问题。

数据准备:

CREATE TABLE user (
id int(11) NOT NULL,
name varchar(32) NOT NULL,
age int(11) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

insert into user (id, name, age) values(‘1’,‘Ada’,‘16’);

### 是否解决了脏读的问题?

![](https://img-blog.csdnimg.cn/img_convert/bf275e4bf7ed17f17fe6aed9e4637d16.png)

开启两个 MySQL 客户端,模拟事务A和事务B的操作,执行步骤如下:

1.  事务B开启手动事务,更新 id=1 的数据,age 更新为18,不提交事务
2.  事务A查询 id=1 的数据
3.  事务B回滚刚才的更新操作

图中的数字是执行步骤,通过下图可以看出事务A的执行结果是16,InnDB 的默认事务隔离级别完美的解决了脏读的问题。

![](https://img-blog.csdnimg.cn/img_convert/dddae630cada358c1df04bf58675678c.png)

### 是否解决了不可重复读的问题?

# **最后**

**最后,强调几点:**

*   1\. 一定要谨慎对待写在简历上的东西,一定要对简历上的东西非常熟悉。因为一般情况下,面试官都是会根据你的简历来问的; 能有一个上得了台面的项目也非常重要,这很可能是面试官会大量发问的地方,所以在面试之前好好回顾一下自己所做的项目;
*   2\. 和面试官聊基础知识比如设计模式的使用、多线程的使用等等,可以结合具体的项目场景或者是自己在平时是如何使用的;
*   3\. 注意自己开源的Github项目,面试官可能会挖你的Github项目提问;

我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!

> **以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目。**

**如何获取整理好的Java面试专题资料?**

**[资料获取方式:点击这里免费下载](https://gitee.com/vip204888/java-p7)**

# **面试答案**

![三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里](https://img-blog.csdnimg.cn/img_convert/0a08d36818e71bf6f224cf4173d5ca3a.png)

![三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里](https://img-blog.csdnimg.cn/img_convert/7eee386343307a5b780f37fe69e26cc5.png)

https://gitee.com/vip204888/java-p7)**

# **面试答案**

[外链图片转存中...(img-5APC65SO-1628065578053)]

[外链图片转存中...(img-vhHVOuOn-1628065578055)]

![三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里](https://img-blog.csdnimg.cn/img_convert/daea65c4f90dbea36b7019d2eac36120.png)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值