👨🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习、
🌌上期文章:MySQL进阶:视图&&存储过程&&存储函数&&触发器
📚订阅专栏:MySQL进阶
希望文章对你们有所帮助
这一部分内容还是很重要的,虽然学起来感觉不是很难,但是要多体会一下,体会好这里的精髓才能更好的理解MySQL事务的锁。
MySQL事务及隔离级别
- 简介
- 事务操作
- 未控制事务
- 控制事务一
- 控制事务二
- 事务四大特性(高频面试题)
- 事务并发问题(重点)
- 事务隔离级别
简介
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
就比如转账,包括加钱和减钱的操作,这一组操作必须在一个事务的范围内,要么都成功,要么都失败。
默认MySQL的事务是自动提交的,也就是说,当执行完一条DML语句时,MySQL会立即隐
式的提交事务。
事务操作
create table account(id int primary key AUTO_INCREMENT comment 'ID',name varchar(10) comment '姓名',money double(10,2) comment '余额'
) comment '账户表';
insert into account(name, money) VALUES ('张三',2000), ('李四',2000);
未控制事务
-- 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 = '李四';
"出错了…"这句话会报错,若不加事务,就会导致张三的钱减少,但是李四的钱没有增加,这就违背了数据一致性
。
控制事务一
1、查看/设置事务提交方式
SELECT @@autocommit ;
SET @@autocommit = 0 ;
2、提交事务
COMMIT;
3、回滚事务
ROLLBACK;
上述的这种方式,是修改了事务的自动提交行为, 把默认的自动提交修改为了手动提交, 此时我们执行的DML语句都不会提交, 需要手动的执行commit进行提交。
控制事务二
1、开启事务
BEGIN; 或 START TRANSACTION;
2、提交事务
COMMIT;
3、回滚事务
ROLLBACK;
事务四大特性(高频面试题)
- 原子性:事务是不可分割的最小单元,要么全成功要么全失败
- 一致性:事务完场时,必须使所有数据保持一致状态
- 隔离性:数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
- 持久性:事务一旦提交或回滚,对数据库中的数据的改变是永久的
事务的四大特性,简称ACID。
事务并发问题(重点)
1、脏读:一个事务读到另外一个事务还没有提交的数据。
B事务的select操作读取到了DB中id=1的数据,但读出来的是事务A执行update后的数据,但事务A根本还没有提交事务。
2、不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
注意:假设此时已经解决了事务的脏读问题
事务A两次读取同一条记录,但是读取到的数据却是不一样的。这是因为在两次select操作之间有一个事务B提交了,事务就是将这一行的数据修改了。
3、幻读:一个事务按照条件查询数据时,没有对应数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了“幻影”。
注意:假设此时已经解决了事务的脏读问题和不可重复读问题
1、事务A执行select,确认了数据库没有id=1的数据
2、事务B执行insert,数据库中增加了id=1的数据
3、事务A执行insert,由于id=1的数据已经存在,无法插入
4、事务A再次执行select,由于已经解决了不可重复读的问题,此时事务A还是没办法获取到id=1的数据
这就是幻读,明明查不到,却插入不进去。
事务隔离级别
为了解决并发事务问题,数据库中引入了事务的隔离级别:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read commited | × | √ | √ |
Repeatable Read(默认) | × | × | √ |
Serializable | × | × | × |
1、查看事务的隔离级别:
SELECT @@TRANSACTION_ISOLATION;
2、设置事务隔离级别:
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED |
READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
需要注意的是,事务的隔离级别越高,数据自然越安全,但是性能会更低。
在这里我们可以看到,MySQL默认的事务隔离级别是RR,脏读和不可重复读的问题是已经解决了,但幻读问题的解决方法是要加一个行级锁——间隙锁&临键锁。