事务是一个操作序列,这些操作要么做,要么不做,是不可分割的工作单位
Mysql默认事务级别 : REPEATABLE-READ
1.查看系统事务级别
select @@session.tx_isolation;
2.查看session事务级别
select @@global.tx_isolation;
事务的结束
1.手动提交commit
2.自动提交,但是一般情况建议将自动提交关闭,因为效率太低
3.用户关闭会话后,会自动提交事务
4.系统崩溃或者断电的时候
savepoint
指定保存某一个点
delete from emp where id = 1;
delete from emp where id = 2;
savepoint sp1;
delete from emp where id = 3;
rollback to sp1;
commit;
事务的ACID属性
原子性、一致性、隔离性、持久性
原子性:表示不可分割,一个操作要么全部成功,要么全部失败,不可切分
一致性: 保证数据存储的完整性;事务系统通过事务的原子、隔离、持久性来满足这一要求
隔离性:各个事务之间不产生影响 (隔离级别)
严格的隔离性会导致效率降低,某些情况为提高性能,会降低隔离级别
隔离级别:
1.读未提交(read uncimmited)
2.读已提交 (read commited)
3.可重复读 (repeated read)
4.序列化 (seriable)
数据不一致问题:
1.脏读
2.不可重复读
3.幻读
持久性:所有修改,都必须持久化到某种物理存储中,不会因为系统的关闭而丢失
这四个特性中哪个最关键?
最终都是为了保证数据的一致性,一致性是通过原子性、隔离性、持久性来保证的
锁的机制: 为保证并发访问,造成数据的一致性,给数据加锁时,考虑颗粒度问题
1.数据库
2.表
3.行
一般情况,锁的粒度越小,效率越高;实际工作中,大部分都是行级锁
脏读 - read uncomited产生
读取到未提交的数据
set session transation isolation level read uncommited;
A:start transation
B:start transtaion;
A: select age from person where id = 1; // age = 10;
A:update person set age = 18 where id = 1;//修改数据,但是未持久化
A: selecgt age from person where id = 1; //age = 18
B: select age from person wehre id = 1; //age = 10;
B: select age person where id = 1; //age = 18; A未提交,读取到脏数据
A:commit;
B: select age person where id = 1; //正常数据,因为A 已经Commit
不可重复读: read uncommited/read commited产生
两次读取的值不一致
set session transation isolation level read commited;
A: start transtion;
B: start transtion;
A: select age from person where id = 1; //age = 10;
B: select age from person where id = 1; // age = 10;
A: update age set age = 18 where id = 1; //未提交;
A: select age from person where id = 1; //age = 18;
B: select age from person where id = 1; //age = 10 //未出现脏读
A:commited;
B: select age from person where id = 1; // age = 18; // B两次读取的数据不一致
幻读: read uncommited/read commited/repeatable 都会产生
事务中未查询ID = 4到数据,但是ID = 4 又的确存在,产生幻觉
set session transation isolation level repeatable read;
A: start transaction;
B: strt transaction;
A: select * from person; //Id为1,2,3的数据
B: select * from person; // Id 为1,2,3的数据
A: INSERT person(id,name) values(4,'zhangsan'); //插入成功
A:commit;
B: select * from person; // Id 为1,2,3的数据
B: INSERT person(id,name) values(4,'lisi')//duplicate key error(系统发现id 4已经存在)// 产生幻读