Java面试题:MySQL之事务



一、含义

一条或多条sql语句组成一个执行单位,一组sql语句要么都执行要么都不执行


二、特点(ACID)

  • 原子性:一个事务是不可再分割的整体,要么都执行要么都不执行,基于日志的 Redo/Undo 机制
  • 一致性:一个事务的执行不能破坏数据库数据的完整性和一致性
  • 隔离性:一个事务不受其它事务的干扰,多个事务是互相隔离的
  • 持久性:一个事务一旦提交了,则永久的持久化到本地

原子性、隔离性、持久性都是为了保障一致性而存在的,一致性也是最终的目的


三、分类

1、隐式事务:没有明显的开启和结束,本身就是一条事务可以自动提交,比如insert、update、delete

2、显式事务:具有明显的开启和结束,例如以下格式:

# 1、开启事务
set autocommit=0;  #关闭自动提交
start transaction; #开启事务机制

# 2、编写一组逻辑sql语句
注意:sql语句支持的是insertupdatedelete

# 【设置回滚点,可选项】
savepoint 回滚点名;

# 3、结束事务
提交:commit;
回滚:rollback;
回滚到指定的地方: rollback to 回滚点名;

# 查看隔离级别 
SELECT @@tx_isolation; 	 

# 设置隔离级别 - 分为全局隔离和会话隔离,会话隔离只对当前窗口有效
SET SESSION|GLOBAL TRANSACTION ISOLATION LEVEL 隔离级别; 

四、事务并发(读问题)

多个事务同时操作同一个数据库的相同数据时会导致事务的并发问题

  • 脏读:该事务读到了另一个事务 未提交的 update 数据
  • 不可重复读:读到了另一个事务 提交的 update 数据
  • 幻读:该事务读到了另一个事务 提交的 insert 数据

如何解决:通过设置事务的隔离级别( √ 代表解决)

隔离级别隔离描述脏读不可重复读幻读
READ UNCOMMITTED读未提交×××
READ COMMITTED读已提交(Oracle默认)××
REPEATABLE READ可重复读(MySQL默认)×
SERIALIZABLE串行化
  • 读未提交:导致读脏,当前事务可以读取其它事务未提交的数据
  • 读已提交:解决读脏,在事务未提交之前所做的 update 其它事务是不可见的,但导致不可重复读
  • 可重复读:解决不可重复读,保证当前事务多次相同的查询的结果是一致的,但导致幻读
  • 可串行化:解决幻读,可串行化就是保证读取的范围内没有新的数据插入,

读已提交演示图
在这里插入图片描述


五、Redo/Undo机制

1、将所有对数据的更新操作都写到日志中

  • Redo log:记录数据修改后的值,可以用来恢复未写入 data file 的已成功事务更新的数据
  • Undo log:记录数据更新前的值,保证数据更新失败能够回滚

假如数据库在执行的过程中,不小心崩了,可以通过该日志的方式,回滚之前已经执行成功的操作,实现事务的一致性。

具体的实现流程:

假如某个时刻数据库崩溃,在崩溃之前有事务A和事务B在执行,事务A已经提交,而事务B还未提交。当数据库重启进行 crash-recovery 时,就会通过Redo log将已经提交事务的更改写到数据文件,而还没有提交的就通过Undo log进行roll back。


六、Mysql的锁机制

类型说明
读锁/共享锁(Shared Locks)读的时候,加共享锁,不能写
写锁/排它锁(Exclusive Locks)写的时候,加排它锁,阻塞其它事务的写入和读取
间隙锁
行锁(Record Locks)增删改时锁当前行,锁的粒度小,加锁慢,锁冲突的概率小,并发度高
表锁增删改时锁当前表,锁的粒度大,加锁快,开销小,锁冲突的概率大,并发度低

间隙锁分为:

  • Gap LocksNext-Key Locks
  • Gap Locks会锁住两个索引之间的区间,比如select * from User where id>3 and id<5 for update,就会在区间(3,5)之间加上Gap Locks
  • Next-Key Locks是Gap Locks+Record Locks形成闭区间锁select * from User where id>=3 and id=<5 for update,就会在区间[3,5]之间加上Next-Key Locks

读未提交是没有加任何锁的,所以对于它来说也就是没有隔离的效果,所以它的性能也是最好的。

串行化加的是一把大锁,读的时候加共享锁,不能写,写的时候,加的是排它锁,阻塞其它事务的写入和读取,若是其它的事务长时间不能写入就会直接报超时,所以它的性能也是最差的,对于它来就没有什么并发性可言。

读提交和可重复读,兼顾解决数据问题,然后又要有一定的并发行,所以在实现上锁机制会比串行化优化很多,提高并发性,所以性能也会比较好。


七、事务底层实现原理 MVCC(多版本并发控制)

实现MVCC时用到了一致性视图,用于支持读提交和可重复读的实现

可重复读:只需要在事务开始的时候创建一致性视图,也叫做快照,之后的查询里都共用这个一致性视图,后续的事务对数据的更改是对当前事务是不可见的,这样就实现了可重复读

读已提交:每一个语句执行前都会重新计算出一个新的视图,这个也是可重复读和读提交在MVCC实现层面上的区别

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Laptoy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值