你的位置:首页 > 数据库

[数据库]SQL SERVER 并发【2015.12.16】


并发控制模型

  1.悲观并发控制:

    A.默认冲突存在,当前进程通过获取当前数据的锁阻止其他进程的访问。

    B.读与写之间是相互阻塞。

  2.乐观并发控制:

    A.使用行版本控制保持数据被操作前的状态。

    B.读与写之间不会相互阻塞;但是写会发生阻塞,SQL SERVER会把冲突的错误信息发送给上层的应用程序。

 

并发造成的数据行为

  1.丢失更新

     当两个进程都读取数据A并修改了数据值,就会造成某个进程修改的数据值被覆盖。

       数据A=10

 时间进程1  进程2
 1SELECT A  
 2 SELECT A 
 3UPDATA A=A+10  
 4 UPDATE A=A+20 

 

 

 

 

 

       
       运行完,数据A=30

       进程1对数据A的修改被丢失了。

  2.脏读

     进程1修改数据A值但未提交,进程2读取了修改后的数据A,随后进程1又回滚了对数据A的修改,造成进程2读取了不一致的状态值。

       数据A=10

 时间进程1  进程2
 1UPDATA A=A+10(未提交) 
 2 SELECT A 
 3UPDATA A=A-10(回滚) 

 

 

 

 

 

       
       A值本身没有变化,但是进程2读取的A值为20。

  3.不可重复读

     进程1读取数据A之后,进程2修改了数据A,进程1再次读取A值,与之前读取的A值不一致。

  4.幻影

     这种行为发生在一个数据集内的部分数据被修改。

 

事务的隔离级别

  事务的隔离性:如果多个事务对同一数据进行处理,就需要对数据进行锁定以保证数据的一致性。

  1.未提交读 (Uncommitted Read)

    事务2可以读取事务1已经修改过但未提交的数据A。

    优点:事务2读取数据A不占用任何锁。

    缺点:无法保证数据的高一致性。

  2.已提交读 (Read Committed)

     事务2只能读取事务1修改并已提交完成的数据A。

    A.已提交读(锁定)-> 悲观并发控制模型

      事务1对数据A持排他锁以进行更新,事务2只能等待这些锁释放以后才能使用这个数据。

      事务2访问数据,最少要对数据加共享锁,如果其它事务要更新数据比较等待。

    B.已提交读(快照)- 乐观并发控制模型

      数据A每次被更新,都会生成最新的快照存储起来,事务读取这个快照,避免读取到未提交的更新值。

  3.可重复读(Repeatable Read)

    在“已提交读”的基础上,增加:事务1两次查询数据A,数据发生改变。这要求共享锁必须保留至事务1结束。

  4.快照(Snapshot)

    类似于“已提交读(快照)”,如果当前版本被锁定,允许读取已提交数据的早期版本。

    与“已提交读(快照)”的区别在于早期版本该有多早这个问题。

    问题:快照隔离,可能导致两个事务同时进行,并引起一个任何序列化执行都不可能产生的结果。

  5.可串行化(Serializable)

    在“可重复读”的基础上增加:同一事务中,重新执行查询,数据集不会发生变化。    

    可以防止幻影行为。