[数据库]事务和隔离级别

一 、事务

1 事务的定义

事务(Transaction)是并发控制的基本单位。事务是构成单一逻辑工作单元的操作集合,要么完整的执行,要么完全不执行。不论任何情况,DBS必须保证事务能正确完整的执行。

##2 事务的特性
● Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败。

● Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态。

● Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。

● Durability(持久性):事务结束后,事务处理的结果必须能够得到固化。

2 并发带来的问题及解决方案

注:以下内容仅代表笔者自己的观点,不具备权威性,请理性参考,欢迎指正

1 脏读

现象:脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
  产生原因(之一):两个事务,事务A读的时候没有加共享锁,事务B插入的时候加了排它锁(加没加不重要),所以在事务A读记录的时候,事务B可以进行插入,所以A读到了B插入的还未提交的数据,但是稍后B回滚了,所以A读到了脏数据,这里的脏数据是指,B插入但是稍后又回滚的数据。
  解决办法(之一):读取数据时加共享锁。

2 不可重复读

现象:同一个事务,查询同一条记录,前后两次的查询结果不同。
  产生的原因(之一):两个事务A和B,A事务两次读取同一条记录,每次读取记录时加共享锁,B在A两次读取之间修改了A要读取的记录,修改时加了排它锁,由于A第一次读取完记录释放了共享锁,所以B修改了该条记录,导致不可重复读。
  解决办法(之一):A事务读取数据时加共享锁,直到A事务结束时才释放该共享锁,这样A两次读取相同记录的间隙,B没有机会修改A要读取的记录。
  在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,例如对于同一个数据A和B依次查询就可能不同,A和B就可能打起来了……

3 幻读(虚读)

现象:同一个事务,用相同的查询条件,前后两次查询得到的结果集不相同,比如说第一次查到了3条,但是第二次查询到了4条。
  举例:假如tab_A的主键是id,SQL:select * from tab_A where id > 0;如果事务A第一次查询该表该表中满足该条件的记录只有3条,id分别为1,2,3,但是在A第二次查询之前,事务B插入一条id = 4的记录,就会导致A第二次再用相同的SQL会查到4条记录。
  产生的原因(之一):A对于第一次读取的三条记录加了共享锁,但是仅对查询出来的满足where条件的记录加了共享锁,还是允许B插入满足查询条件的记录,就导致了幻读。
  解决办法(之一):不允许B在A两次查询之间想要插入满足A查询条件的记录即可解决幻读问题。

二 隔离级别

这里写图片描述

1 可读未提交(Read uncommitted)

写事务阻止其他写事务,避免了更新遗失。但是没有阻止其他读事务。
存在的问题:脏读。
解决办法就是下面的“Read committed”。

2 可读已提交(Read committed)

写事务会阻止其他读写事务。读事务不会阻止其他任何事务。
存在的问题:不可重复读。
解决办法就是下面的“可重复读”。

3 可重复读(Repeatable read)

读事务会阻止其他写事务,但是不会阻止其他读事务。
存在的问题:幻读。
解决办法就是下面的“串行化”。

4 串行化(Serializable)

读对满足条件的记录加共享锁且不允许插入满足查询条件的记录,直到事务结束才释放锁,写加排他锁。这样读取事务可以并发,但是读写,写写事务之间都是互斥的,基本上就是一个个执行事务,所以叫串行化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章