zoukankan      html  css  js  c++  java
  • 数据库事务的四大特性

    一个设计良好的数据库可以帮我们保证事务具有四大特性(ACID):

    原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

    一致性:如果事务执行之前数据库是一个完整的状态,那么事务结束后,无论事务是否执行成功,数据库仍然是一个完整的状态。

      数据库的完整状态:当一个数据库中的所有的数据都符合数据库中所定义的所有约束,此时可以称数据库是一个完整的状态。

    隔离型:多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离。

    持久性:指一个事务一旦被提交,他对数据库的影响是永久性的。

    数据库可以保证原子性,一致性,持久性。但是隔离级别需要根据并发情况进行设置,

    将数据库设计成单线程,可以防止所有的线程安全问题,自然也就保证了隔离型的问题,但是如果这样,那么效率就会极其低下。

    如果两个线程并发修改,一定会相互捣乱,这时必须利用锁机制防止多个线程的并发修改

    如果两个线程并发查询,没有线程安全问题。

    如果两个线程一个修改,一个查询:

      四大隔离级别:

      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;
    ------------

  • 相关阅读:
    Windows Azure Cloud Service (14) 使用Windows Azure诊断收集日志记录数据
    Windows Azure Cloud Service (13) 用Visual Studio 2010 将应用程序部署到Windows Azure平台
    Windows Azure Cloud Service (15) 多个VM Instance场景下如何处理ASP.NET Session
    Windows Azure Storage (5) Windows Azure Drive
    Windows Azure Storage (7) 使用工具管理Windows Azure Storage
    SQL Azure(二) SQL Azure vs SQL Server
    webbrowser的自动提交
    提取视频的背景声音的软件
    Listview列排序的bug原因
    两个奇怪的问题
  • 原文地址:https://www.cnblogs.com/cristin/p/7732239.html
Copyright © 2011-2022 走看看