🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄
🌹简历模板、学习资料、面试题库、技术互助
🌹文末获取联系方式 📝
往期热门专栏回顾
MySQL专栏回顾
专栏 | 导航 | 描述 |
---|---|---|
MySQL | - - | MySQL DDL通用语法 |
MySQL | - - | MySQL DML通用语法 |
MySQL | - - | MySQL 约束篇 |
MySQL | - - | MySQL 多表查询 |
MySQL | - - | MySQL 事务 |
前言
此为MySQL专栏文章之一,讲解MySQL 事务。
事务是逻辑上一组操作的集合,事务会把所有操作作为一个整体一起向系统 提交 或 撤销 操作请求,即这些操作要么同时成功,要么同时失败。
1、事务演示
1.1、基本操作
-- 1. 查询张三账户余额
select * from account where name = '张三';
-- 2. 将张三账户余额-1000
update account set money = money - 1000 where name = '张三';
-- 此语句出错后张三钱减少但是李四钱没有增加
模拟sql语句错误
-- 3. 将李四账户余额+1000
update account set money = money + 1000 where name = '李四';
-- 查看事务提交方式
SELECT @@AUTOCOMMIT;
-- 设置事务提交方式,1为自动提交,0为手动提交,该设置只对当前会话有效
SET @@AUTOCOMMIT = 0;
-- 提交事务
COMMIT;
-- 回滚事务
ROLLBACK;
-- 设置手动提交后上面代码改为:
select * from account where name = '张三';
update account set money = money - 1000 where name = '张三';
update account set money = money + 1000 where name = '李四';
commit;
1.2、操作方式二
开启事务:
START TRANSACTION 或 BEGIN TRANSACTION;
提交事务:
COMMIT;
回滚事务:
ROLLBACK;
操作实例:
start transaction;
select * from account where name = '张三';
update account set money = money - 1000 where name = '张三';
update account set money = money + 1000 where name = '李四';
commit;
2、 四大特性ACID
● 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败
● 一致性(Consistency):事务完成时,必须使所有数据都保持一致状态
● 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
● 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的
3、并发事务存在的问题
不可重复读:破坏了一致性,update 和 delete
幻读:破坏了一致性 insert
不可重复读和幻读的区别
● 不可重复读的重点是内容修改或者记录减少比如多次读取一条记录发现其中某些记录的值被修改;
● 幻读的重点在于记录新增比如多次执行同一条查询语句(DQL)时,发现查到的记录增加了。
幻读其实可以看作是不可重复读的一种特殊情况,
单独把区分幻读的原因主要是解决幻读和不可重复读的方案不一样。
举个例子:执行 delete 和 update 操作的时候,可以直接对记录加锁,保证事务安全。
而执行 insert 操作的时候,由于记录锁(Record Lock)只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁(Gap Lock)。
也就是说执行 insert 操作的时候需要依赖 Next-Key Lock(Record Lock+Gap Lock)
进行加锁来保证不出现幻读。
4、并发事务隔离级别
读未提交:原理:直接读取数据,不能解决任何并发问题
读已提交:读操作不加锁,写操作加排他锁,解决了脏读。原理:利用MVCC实现,每一句语句执行前都会生成Read View(一致性视图)
可重复读:MVCC实现,只有事务开始时会创建Read View,之后事务里的其他查询都用这个Read View。解决了脏读、不可重复读,快照读(普通查询,读取历史数据)使用MVCC解决了幻读,当前读(读取最新提交数据)通过间隙锁解决幻读(lock in share mode、for update、update、detete、insert),间隙锁在可重复读下才生效。(默认隔离级别)
可串行化:原理:使用锁,读加共享锁,写加排他锁,串行执行
总结:
读已提交和可重复读实现原理就是MVCC Read View不同的生成时机。
可重复读只在事务开始时生成一个Read View,之后都用的这个;读已提交每次执行前都会生成Read View。
MySQL 在 InnoDB下是默认可重复读的隔离级别,加上 MVCC机制 解决了脏读、不可重复读、幻读的问题。
● √ 表示在当前隔离级别下该问题会出现
● Serializable 性能最低;Read uncommitted 性能最高,数据安全性最差
● 在 MySQL 的 InnoDB 引擎下,Repeatable Read 其实不会发生幻读(MVCC机制)。
● 自 MySQL5.5 之后,默认的存储引擎是 Innodb。
查看事务隔离级别:
SELECT @@TRANSACTION_ISOLATION;
设置事务隔离级别:
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };
SESSION 是会话级别,表示只针对当前会话有效,GLOBAL 表示对所有会话有效
5、实现事务的原理
MySQL 中的 ACID 实现原理:
原子性:undolog(记录事务开始前的老版本数据,可以保证原子操作,回滚,实现MVCC版本链)
隔离性:读写锁 、MVCC
持久性:redo log(记录事务开启后对数据的修改,可用于crash-safe)
资料获取,更多粉丝福利,关注下方公众号获取