zoukankan      html  css  js  c++  java
  • 数据库的并发处理之悲观锁与乐观锁

      概述

    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

          

  • 相关阅读:
    IE8下部分方法失效的解决方法
    C#获取本机IP地址(ipv4)
    WPF中控制窗口显示位置的三种方式
    JS判断IP的正则表达式
    WPF ListView 简单的拖拽实现(转)
    C# 中取绝对值的函数
    移动端rem单位适配使用
    vue中遇到的坑!!!!!
    vux安装中遇到的坑
    移动端常用的代码
  • 原文地址:https://www.cnblogs.com/chenxizhaolu/p/8671454.html
Copyright © 2011-2022 走看看