事务的特性
- 原子性 :在同一在项业务处理过程中,事务保证了对多个数据的修改,要么同时成功要么同时被撤销
- 隔离性:在不同的业务处理过程中,事务保证了各业务在读写的数据相互独立,不会彼此影响。
- 持久性:事务保证所有成功被提及的数据修改都能够正确地被持久化不丢失数据。
- 一致性:通过上面三个方便,保证系统中的数据都是符合期望的,且相互关联的数据之间不会产生矛盾,即数据状态的一致性。
事务的锁和隔离级别
锁
- 写锁:也叫排他锁,简称X-Lock 如果数据有加写锁,就只有持有写锁的事务才能对数据进行写入操作,数据加写锁时,其他事务不能写入数据,也不能施加写锁。
- 读锁:也叫共享锁,简称S-Lock 多个事务可以对一个数据添加多个读锁,数据在被加上读锁后就不能在加写锁,所以其他事物不能对数据进行写入,但不影响读,当拥有读锁的事务可以进行锁升级,加上写锁
- 范围锁:对某个范围加上排他锁,在这个范围内的数据不能被写入
select * from user where age < 10 for update;
隔离级别
- 可串行化 所有操作都加上读锁,写锁和范围锁即做到可串行化(简化理解实际更复杂)。
- 可重复读(mysql-InnoDB默认) 对事务涉及到数据加读锁和写锁,且一直持续到事务结束,但不在加范围锁。比可串行化有些偏弱,会出现幻读的问题。幻读是指:在事务执行过程中,两个完全相同的范围查询得到不同的结果集。
比如
select count(1) from user where age < 10; 执行顺序 1 事务T1
insert into user(name,age) values('yyl',5); 执行顺序 2 事务T2
select count(1) from user where age < 10; 执行顺序 3 事务T1
- 读已提交 对事务设计的数据加写锁一直到事务结束,但加的读锁在查询操作后会马上释放。读已提交比可重复读偏弱,在与不可重复读问题。是指事务在执行过程中,同一行数据的两次查询得到不同的结果。
比如
select * from user where id = 1; 执行顺序 1 事务T1
update user set age = 10 where id = 1 ; commit;执行顺序 2 事务T2
select * from user where id = 1; commit; 执行顺序 3 事务T1
如果隔离级别是读已提交,这两次的查询结果会不一样,原因是读已提交的隔离级别缺乏贯穿整个事务周期的读锁,无法禁止读取过的数据发生变化,此时事务T2更新语句可以提交成功。影响了T1 的查询结果。可重复读级别不会释放读锁,其他事务插不进去。
- 读未提交 只会对事务设计的数据加些锁,且一直持续到事务结束,但完全不加读锁,比读已提交偏弱,在于脏读问题,指一个事务执行过程中,一个事务读取到另一个事务未提交的数据,
比如
select * from user where id = 1; 执行顺序 1 事务T1
update user set age = 10 where id = 1;执行顺序 2 事务T2
// 注意没有commit
select * from user where id = 1; 执行顺序 3 事务T1
ROLLBACK;执行顺序 4事务T2