数据库事务的四大特性

    xiaoxiao2021-04-12  29

         事务四大特性(简称ACID) 

    1、原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行。

    2、一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。

    3、隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。

    4、持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。   

            数据库可以保证原子性,一致性,持久性。但是隔离级别需要根据并发情况进行设置,将数据库设计成单线程,可以防止所有的线程安全问题,自然也就保证了隔离型的问题,但是如果这样,那么效率就会极其低下。如果两个线程并发修改,一定会相互捣乱,这时必须利用锁机制防止多个线程的并发修改。如果两个线程并发查询,没有线程安全问题。

      四大隔离级别

      Read uncommitted:---不防止任何隔离型问题,不能防止脏读/不可重复读/幻读问题。

      Read commit:---可以防止脏读问题,但是不能防止 不可重复读/幻读问题。(oracle默认隔离级别)

      Repeatable read:---可以防止脏读/不可重复读,不能防止幻读。(mysql默认隔离级别)

      Serializable:--数据库被设计为单线程,可以防止上述所有问题

      脏读:一个事务读取到另一个事务未提交的数据。

      场景:a账户1000,b账户1000,a到b的网店里买一百块钱的鞋子。。。。

      a:start transaction

      update table set money=money-100 where name='a';//a账户扣除100

      update table set money=money+100 where name='b';//b账户增加100

      此时a还没有提交事务,对b说付款成功

      b:start transaction;//b开始查询自己的账户余额

      select money form table where name='b';

      b:commit;

      如果读取到了a没有提交的数据,那么b查出来的就会是1100,此时b开始发货

      此时a执行回滚

      a:rollback;

      那么b再去查询账户余额会发现自己的账户还是原先的100块

     

      不可重复读:在当前事务中,读取到了另一事务提交的更新和删除的数据。

      场景:如果a有活期资金1000,定期1000,固定资产1000

      a: 1000 1000 1000   b: 银行职员,银行让职员b算出a客户的总共资产   ---------   b:start transaction;   select 活期存款 from account where name='a'; ---- 活期存款:1000   select 定期存款 from account where name='a'; ---- 定期存款:1000   select 固定资产 from account where name='a'; ---- 固定资产:1000      -------此时a客户取走了自己活期的1000元     a:     start transaction;     update accounset set 活期=活期-1000 where name='a';     commit;   -------   select 活期+定期+固定 from account where name='a'; --- 总资产:2000,按照之前查出来的应该是3000元,但是现在是2000元   commit;   ----------

      但是虽然在这种场景下,出现了不可重复读,但是如果在另一场景下,如果你和你的伙伴共用一个银行账户共100万,你的伙伴如果中途取走了50万,而你此时读取到剩下的50万,就符合该场景。

      幻读:在当前事务中,读取到了另一事务提交的插入的数据

      场景:如果银行现在有a、b两位客户存款各1000,银行老板让职员b去算平均每个客户的平均存款,而又有新增客户c存入了4000元。

      a: 1000   b: 1000   d: 银行业务人员   -----------   d:   start transaction;   select sum(money) from account; --- 2000 元   select count(name) from account; --- 2 个   ------   c: start transaction; insert into account values(c,4000); commit; ------ select sum(money)/count(name) from account; --- 平均:2000元/个,结果应该是平均存款1000,而实际结果确实2000 commit; ------------

    转载请注明原文地址: https://ju.6miu.com/read-668268.html

    最新回复(0)