数据库隔离的四个级别
数据库隔离的四个级别分别为:
Read Uncommitted(读未提交)
在一个事务处理过程里读取了另一个未提交的事务中的数据。会导致脏读。
脏读(Drity Read):
某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个回滚了操作,则后一个事务所读取的数据就会是不正确的。
举个例子,公司发工资了,领导把四万块钱打到我的账号上,但是该事务并未提交,而我正好去查看账户,发现工资已经到账,是四万,非常高兴。可是不幸的是,领导发现发给我的工资金额不对,是三万五元,于是迅速修改金额,将事务提交,最后我实际的工资只有三万五元,我就白高兴一场。
Read Committed(读已提交)
这是大多数数据库系统的默认隔离级别,但不是MySQL默认的。会导致不可重复读,事务a读取数据,事务b立马修改了这个数据并且提交事务给数据库,事务a再次读取这个数据就得到了不同的结果。
不可重复读(Non-repeatable read):
在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间更新了原有的数据。
举个例子,我拿着工资卡去消费,系统读取到卡里确实有一百块钱,这个时候我的女朋友刚好用我的工资卡在网上转账,把我工资卡的一百块钱转到另一账户,并在我之前提交了事务,当我扣款时,系统检查到我的工资卡已经没有钱,扣款失败,廖志伟十分纳闷,明明卡里有钱的。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。会导致幻读,InnoDB和Falcon存储引擎通过多版本并发控制机制解决了该问题。
幻读(Phantom Read):
在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
举个例子,当我拿着工资卡去消费时,一旦系统开始读取工资卡信息,这个时候事务开始,我的女朋友就不可能对该记录进行修改,也就是我的女朋友不能在这个时候转账。这就避免了不可重复读。假设我的女朋友在银行部门工作,她时常通过银行内部系统查看我的工资卡消费记录。有一天,她正在查询到我当月信用卡的总消费金额(select sum(amount) from transaction where month = 本月)为80元,而我此时正好在外面胡吃海喝后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction … ),并提交了事务,随后我的女朋友把我当月工资卡消费的明细打印到A4纸上,却发现消费总额为1080元,我女朋友很诧异,以为出现了幻觉,幻读就这样产生了。
Serializable(可串行化)(更高级别隔离,避免脏读,避免不可重复读,避免幻读)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
ACID底层实现原理
原子性底层实现原理
A(原子性),要么全部完成,要么完全不起作用。底层实现是通过undo log日志去实现的,当这个事务对数据库进行修改的时候,innodb 生成对应undo log,undolog有多个版本,并且存放的是与上一个版本相反的操作,他会记录这个SQL执行的相关信息,如果SQL执行失败发生回滚,innodb 根据这个undo log内容去做相反的工作,比如说我执行了一个insert 操作,那么回滚的时候,就会执行一个相反的操作,就是delete,对应update,回滚的时候也是执行相反的update。这就是原子性的底层实现。
一致性实现原理
一旦事务完成,不管成功还是失败,数据处于一致的状态,而不会是部分完成,部分失败。事务执行前后,数据库的完整约束没有遭受破坏,事务执行前后都是合法的一个数据状态。事务的AID是数据库的特征,也就是依赖数据库的具体实现。而唯独这个C,实际上它依赖于应用层,也就是依赖于开发者。这里的一致性,是指数据从一种正确的状态,跳转到另一种正确的状态。
举例:账户A转1000到账户B,A转账的金额,必须小于等于自己的账户余额,即事务提交时,A的账户余额不能为负数,可以通过数据库约束,保证账户金额的字段值大于等于0。
- 点赞
- 收藏
- 关注作者
评论(0)