数据库事务的四大特点
上学的时候我们都学过事务的四大特点ACID,很多时候我们都不知道ACID到底是个什么东西?今天我们就来好好分析分析是什么叫做ACID。
- A(Automicity)
就是我们经常所说的原子性,所谓的原子性,就是一组操作要么不做要么全做,不能有做了一半的情况。 - C (Consistency)
一致性,是指事务必须使数据库从一个一致性状态切换到另外一个一致性状态,也就是事务在执行前和执行之后状态必须一致。
看到一个很好的说明一致性的例子,银行两个账户总共1万块钱,不论他们之间发生多少次转账,总共的金额应该是1万块不变。
- I (Isolayion)
隔离性,就是多个并发事务会被隔离开,相互之间不会互相干扰。
例如多个用户在操作数据库同一张表的时候,会产生多个事务,这些事务执行是串行化的。
- D (Durability)
永久性,也就是这个事务被提交了,就不会再被更改了。
如果没有事务的隔离性,会发生什么呢?
- 脏读
有两个事务,A和B,如果同时操作数据库的同一张表,在没有隔离性的前提下,A的操作尚未提交,B同时操作的话,B会读到A尚未提交的数据,这就造成了脏读。
update account set money=money+100 where name=’B’; (此时A通知B)
update account set money=money - 100 where name=’A’;
如果执行完一个update,此时b去查询的时候发现账户确实多了100,而后一个update执行失败,事务回滚,此时b的账户并没有多100块,就会造成脏读。
- 不可重复读
不可重复读是指,在一个事务里多次查询得到的结果不一致,原因是因为在这个事务执行的同时其他事务操作了数据并且已经提交。
// 第一个事务第一查询
select * from t_user t where t.name like '%a%';
// 第二个事务执行了update,并且已经提交
update t_user set name value =' amily';
// 第一个事务再次查询
select * from t_user t where t.name like '%a%';
这样两次查询的结果就是不一致的。
脏读和不可重复读的区别是什么呢?
脏读是一个事务读到另一个事务未提交的数据,不可重复读是指一个事务读到另一个已经提交了的事务。
- 幻读
幻读是事务非独立执行的一种现象。例如事务a把数据库里面某张表的数据从1修改为2,这时事务b往数据库里面有插入了一条为1的数据,这时事务a再做查询的时候会发现有多出了一个为1的记录,就会感觉很奇怪,以为自己产生幻觉了,所以就叫做幻读了,其实这个时候读到的数据是事务b插入到数据库的。
// 第一个事务更新
update t_user set name=2 where name=1;
// 第二个事务insert
insert into t_user (name) value (1);
// 第一个事务查询
select * from t_user t where t.name = 1;
数据库事务的四大隔离级别
- read-uncommitted
读未提交,如果是读未提交肯定会出现脏读,幻读,不可重复读 - read-committed
读已提交,如果读已经提交的话,肯定不会出现脏读了,但是幻读,不可重复读肯定还是会出现的 - repeatable-read (mysql innodb默认的)
重复读,可以避免脏读和不可重复读,通过间隙锁可以避免幻读。 - serializable
串行化,这个就牛逼了,意思就是一个一个的来,当然什么不可重复读,幻读,脏读统统的搞定。
总结一下:
隔离级别 | Dirty reads | non-repeatable reads | phantom reads |
---|---|---|---|
Serializable | 不会 | 不会 | 不会 |
READ COMMITTED | 不会 | 会 | 会 |
REPEATABLE READ | 不会 | 不会 | 会 |
Read Uncommitted | 会 | 会 | 会 |
性能来说的话是:
read-uncommitted>read-committed>reaptable-read>serializable
从隔离性来说:
read-uncommitted<read-committed<reaptable-read<serializable