事务是数据库管理系统执行过程当中的一个逻辑单位,由一个有限的数据库操做序列构成。--摘自百科java
在MySQL里,事务是在引擎层面实现,好比MyIsam不支持,InnoDB支持mysql
提到事务,确定会想到 ACID 是吧,自行感觉一下概念,而后咱们来说讲隔离性的问题。面试
原子性:事务的全部操做要么所有成功,要么所有回滚。sql
一致性:老是从一个一致性的状态转换到另外一个一致性的状态。数据库
隔离性:多个事务并发执行时,一个事务的执行不该影响其余事务的执行 session
持久性:已被提交的事务对数据库的修改应该永久保存在数据库中。并发
作了多年的 CRUDer,对这几个词真是不陌生,要不是出去面试,也真不会去了解。但愿你们看完以后,面试的时候,不要慌,跟他刚。测试
实际上,这些场景都是出如今多个事务同时执行时的场景。spa
通俗的讲,一个事务在处理过程当中读取了另一个事务未提交的数据。code
你都还没提交,我就读到了你刚操做的数据,万一你回滚了怎么办,你说这脏不脏。
举例:
假设打赏的逻辑是:① 个人帐户+1元;② 你的帐户-1元。
当你执行到第一个步骤,我去查询个人帐户已是2元了,很开心!!!宣布请你们去撸串!!!可是最后扣款的时候发现你余额不足了,回滚了,个人1元没了,就很难受!!
通俗的讲,一个事务范围内,屡次查询某个数据,却获得不一样的结果。
与脏读的区别:脏读是读到未提交的数据,而不可重复读读到的倒是已经提交的数据,但其实是违反了事务的一致性原则。
举例:
假设我查了下帐户余额,看到大家给小编打赏了1块钱,很开心!!!宣布请你们去撸串!!!在付款以前,钱被另一我的取走,又查询到没钱了,被留下来洗碗了!!!
由于我查询完后,这条数据没锁住,又被别的事务更新了,致使当前事务每次都是读到最新的数据。

在Repeatable Read隔离级别下,一个事务可能会遇到幻读(Phantom Read)的问题。
事务A读取与搜索条件相匹配的若干行。事务B以插入或删除行等方式来修改事务A的结果集,而后再提交。
举例:
实际上,在InnoDB引擎中,对于索引的扫描,不只锁住扫描到的索引,并且还锁住这些索引覆盖的范围(gap),所以这个范围是内插入数据是不容许的。
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
SET SESSION TRANSACTION ISOLATION LEVEL read uncommitted;
SET SESSION TRANSACTION ISOLATION LEVEL read committed;
SET SESSION TRANSACTION ISOLATION LEVEL repeatable read;
SET SESSION TRANSACTION ISOLATION LEVEL serializable;
start transaction;
--建表
drop table AMOUNT;
CREATE TABLE `AMOUNT` (
`id` varchar(10) NULL,
`money` numeric NULL
)
;
--插入数据
insert into amount(id,money) values('A', 800);
insert into amount(id,money) values('B', 200);
insert into amount(id,money) values('C', 1000);
--测试可重复读,插入数据
insert into amount(id,money) values('D', 1000);
--设置事务
SET SESSION TRANSACTION ISOLATION LEVEL read uncommitted;
SELECT @@tx_isolation;
--开启事务
start transaction;
--脏读演示,读到其余事务未提交的数据
--案列1,事务一:A向B转200,事务二:查看B金额变化,事务一回滚事务
update amount set money = money - 200 where id = 'A';
update amount set money = money + 200 where id = 'B';
--不可重复读演示,读到了其余事务提交的数据
--案列2,事务一:B向A转200,事务二:B向C转200转100
SET SESSION TRANSACTION ISOLATION LEVEL read committed;
--开启事务
start transaction;
--两个事务都查一下数据(转帐以前须要,查一下金额是否够知足转帐)
select * from amount;
--事务一:B向A转200
update amount set money = money - 200 where id = 'B';
update amount set money = money + 200 where id = 'A';
commit;
--事务二:B向C转200转100
update amount set money = money - 100 where id = 'B';
update amount set money = money + 100 where id = 'C';
commit;
--从事务二的角度来看,读到了事务一提交事务的数据,致使金额出现负数
--幻读演示
--案列3,事务一:B向A转200,事务二:B向C转200转100
SET SESSION TRANSACTION ISOLATION LEVEL repeatable read;
--开启事务
start transaction;
--两个事务都查一下数据(转帐以前须要,查一下金额是否够知足转帐)
select * from amount;
--事务一:B向A转200
update amount set money = money - 200 where id = 'B';
update amount set money = money + 200 where id = 'A';
commit;
--事务二:B向C转200转100
update amount set money = money - 100 where id = 'B';
update amount set money = money + 100 where id = 'C';
commit;
--从事务二的角度来看,读到了事务一提交事务的数据,致使金额出现负数
复制代码