事务与锁
1. 事务
1.1 什么是事务
要么都成功,要么都失败
(1)事务原则(ACID)
原子性(Atomicity):要么都成功,要么都失败。
一致性(Consistency):事务前后的数据完整性要保证一致。
隔离性(Isolation):多个用户并发访问数据库时,数据库为每个用户开启的事务不能被其他事务的操作所干扰。
持久性(Durability):事务一旦提交则不可逆,被持久化到数据库中。
事务的隔离性是通过锁实现,而事务的原子性、一致性和持久性是通过事务的日志实现的。
(2)事务的隔离级别(隔离性产生的问题)
赃读:指一个事务读取了另外一个事务未提交的数据。
不可重复读:在一个事务内读取表中某一行数据,多次读取结果不同。(不一定是错误,只是某些场合不对,主要指其他事务的更新语句和删除语句的影响)
幻读:指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。(主要指其他事务的插入语句的影响)
(3)执行事务的原理
-- 1.mysql是默认开启事务自动提交的
set autocommit = 0 --关闭
set autocommit = 1 --开启(默认的)
-- 2.1手动开启事务
set autocommit = 0
-- 2.2事务开启
start transaction --标记一个事物的开始,从这个之后的sql都在同一个事务内
insert...... --模拟一个事务
insert...... --模拟一个事务
-- 2.3提交:持久化(成功!)
commit
-- 2.4回滚:回到原来的样子(失败的话)
rollback
-- 2.5事务结束
set autocommit = 1
事务的执行过程如下,以 begin
或者 start transaction
开始,然后执行一系列操作,最后要执行 commit
操作,事务才算结束。当然,如果进行回滚操作(rollback
),事务也会结束。需要注意的是,begin
命令并不代表事务的开始,事务开始于begin
命令之后的第一条语句执行的时候。
![c077d9f78ff55563030b8a165336383a.png](https://i-blog.csdnimg.cn/blog_migrate/3d82c71ef18fc4f7dfaeeaf36da4e74f.png)
(4)事务的四种隔离级别
- 读未提交、读已提交、可重复读、串行化:
![33ffab5f2163ff76c890df43f444d1e7.png](https://i-blog.csdnimg.cn/blog_migrate/baac1282765e49ccf043cd4cc51df364.png)
说明:
1)一般不考虑读未提交和串行化。因为读未提交什么问题都没有解决,而序列化虽然解决了所有的问题,但是序列化杜绝了并发问题,改为串行执行了,没有太大的意义,性能反而越来越低了。
2)主要使用的是可重复读,它是InnoDB引擎默认使用的隔离级别;不可重复读是Oracle默认使用的隔离级别。
扩展:思考题:
![aafe70e49be6c507051902a7d6292e96.png](https://i-blog.csdnimg.cn/blog_migrate/b8ab5678f3f54a320839811993ed7e4b.png)
参考答案:
读未提交:V1=20;V2=20;V3=20
读已提交:V1=18;V2=20;V3=20
可重复读:V1=18;V2=18;V3=20
序列化:V1=18;V2=18;V3=20
1.2 事务高级语法
-- 1.查看事务是否已经开启(默认开启的ON)
show variables like 'autocommit'
-- 2.autocommit等同于以下一系列操作
begin;
update ...;
delete...;
insert...;
commit;
rollback;
1.2.1 事务隔离级别的实现方式
主要指的是可重复读的实现方式。主要靠锁来实现的。
总结:读已提交解决了脏读问题,行锁解决了并发更新的问题。并且 MySQL 在可重复读级别解决了幻读问题,通过行锁和间隙锁的组合 Next-Key 锁实现的。
-- 1.查看当前数据库使用的是哪种隔离级别?
show variables like 'transaction_isolation';
1)LBCC(Lock-Based Concurrent Control,基于锁的并发控制)、MVCC(Multi-Version Concurrent Control,多版本并发控制,行级锁的变种)。
2)表锁和行锁
![0bab606ea5a7acc9f5dc982c948b05a4.png](https://i-blog.csdnimg.cn/blog_migrate/b25e9bea0824ef9cb26be96b02bf7d10.png)
表锁(类似于订整个酒店),行锁(类似于订酒店里的一个房间)。行锁与表锁是基于索引来说的(且索引要生效),不带索引 (表锁)要全表扫描。
3)InnoDB锁
角度一:锁的模式
![8e75eaa991aa98ac2a71566b0e611f26.png](https://i-blog.csdnimg.cn/blog_migrate/3fad1b5544d6ce3ebec9595d4f495893.png)
3.1 共享锁(行锁)——Shared Locks
又名读锁(简称S锁),对某一资源加共享锁,自身可以读该资源,其他人也可以读该资源(也可以再继续加共享锁,即共享锁可以多个加在同一个记录上),但无法修改。要想修改就必须等待所有共享锁都释放完之后才能进行。
-- 1.加锁
select * from table_nale lock in share mode; -- lock in share mode
-- 2.释放锁
commit;
rollback;
情况一:有且仅有我自己访问,我加了行锁后,我仍然可以更改数据;
情况二:还有别人的读锁时,我就不能再修改了。
应用场景:财务统计。
3.2 排它锁(行锁)——Exclusive Locks
又名写锁(简称X锁),多某一资源加排他锁,自身