• 数据库的并发处理之悲观锁与乐观锁


      概述

    1. 何为并发?并发是指两个或多个事件在同一时间间隔内发生。
    2. 程序去预防并发的基本思路就是讲并行执行改为串行执行,也就是拉队列。
    3. 数据库针对并发的处理一般采用悲观并发处理和乐观并发处理。
    4. 数据库悲观锁是一种串行运算,假定会发生并发冲突,屏蔽一些可能违法数据完整性的操作。悲观锁假定其他用户企图访问或者更改对象的效率是很高的,所以会在程序开始改变对象之前就将对象锁住,知道提交了所做的更改之后才释放所。缺点是不论是页锁还是航所,加锁时间可能会很长,这样可能会长时间锁定一个对象,限制其他对象访问,并发访问性不好。
    5. 数据库乐观锁是一种并行运算,只是在提交操作时检查是否违反数据完整性。乐观锁不能解决脏读问题。乐观锁假定不会发生并发冲突,因此知道程序准备提交所做的更改时才将对象锁住,当程序读取以及改变对象时并不加锁。乐观锁加锁时间要比悲观锁短,可以用于较大锁力度获得较好的并发访问性能。由于用户提交时,数据库对象可能已经发生了变化,这样用户不得不重新读取对象,增加了用户读取对象的次数。

      实践

        悲观者方法

        加了updlock锁,锁定了更新操作。

          

    ALTER PROCEDURE [dbo].[beiguansuo]
    AS
    BEGIN
    	declare @age int 
    	begin tran
    	select @age=age from Student with(updlock) where  FirstName='fengjie'
    	waitfor delay '00:00:05'
    	update [dbo].[Student] set Age=@age-1 where FirstName='fengjie'
    	commit tran
    END
    

      乐观者方法

      数据库列有一个类型为“timestamp”,是一个时间戳,可以理解为版本号。一旦有访问者修改了该数据,版本号的值就会发生改变。我们在更改数据之前首先获取该记录的版本号,然后在记录更新的时候通过主键和版本号同时去更新。但是这样会出现一个问题,如果我们拿到版本号后,数据已经被修改了,这时候update的影响行数为0。所以在这里程序需要根据返回行做特殊处理,可以提醒用户刷新后再修改,也可以递归去Update,根据具体的业务场景选择不同的方法。

      

    ALTER PROCEDURE [dbo].[leguansuo]
    AS
    BEGIN
    	declare @rowversion timestamp
    	declare @age int
    	
    	select @rowversion=RowVersion,@age=Age from Student
    
    	update Student set Age=@age-1 where FirstName='fengjie' and RowVersion=@rowversion
    END
    
    Main(){
    var upRows = executeLeguansuo();
                int retry = 10;
                while (upRows==0&&retry>0)
                {
                    Thread.Sleep(500);
                    retry--;
                    upRows = executeLeguansuo();
                }
    }

    private int executeLeguansuo() {
                string sql = "exec leguansuo";
                using (myEntities context = new myEntities())
                {
                    int upRows = context.Database.ExecuteSqlCommand(sql, new object[] { });
                    if (upRows==0)
                    {
                        executeLeguansuo();
                    }
                    return upRows;
                }
            }

      EF框架如何避免数据库并发

        在EF DataBaseFirst中,只需要设置类型为TimeStamp版本号的并发模式属性即可。默认是None,设置为Fixed即可。

      在线系统发生并发时,程序会抛出异常,我们捕获这个异常然后结合业务场景选择不同的处理方式即可。

      

    public class SaveChangesForBF : BingFaTestEntities
        {
            public override int SaveChanges()
            {
                try
                {
                    return base.SaveChanges();
                }
                catch (DbUpdateConcurrencyException ex)//(OptimisticConcurrencyException)
                {
                    //并发保存错误
                    return -1;
                }
            }
        }

      本文有内容引用自:http://www.cnblogs.com/chenwolong/p/BF.html

          

  • 相关阅读:
    Python 面向对象4-特殊成员
    Python 面向对象3-成员修饰符
    Python 面向对象2
    Python 面向对象
    Python hashlib模块
    使用Access-Control-Allow-Origin解决跨域
    倒计时
    移动端之touch事件--手指的滑动事件
    HTML5获取地理经纬度并通过百度接口得到实时位置
    h5直播
  • 原文地址:https://www.cnblogs.com/chenxizhaolu/p/8671454.html
Copyright © 2020-2023  润新知