zoukankan      html  css  js  c++  java
  • 保证一个用户已选取的记录不被其他用户选取

    问题描述:
      用ADO访问数据库,从一个表中取一定的记录(比如20行),取出后在程序中使用,使用完后删除掉记录(不用更新或删除记录)。在多用户操作下(每个用户采用相同的操作),怎么保证一个用户已选取的记录不被其他用户选取?
      
      问题解决:
      处理这类问题的一般方法是增加一个标志列,每个用户取的记录设置一个标志,新的用户只从标志为未取的记录中获取记录。
      而本文利用事务与锁来控制数据的处理,不需要增加任何标志列
      下面是具体的解决示例
      
      1. 建立测试环境
      USE tempdb
      GO
      
      CREATE TABLE dbo.tb(
      id int identity(1, 1),
      name nvarchar(128))
      
      INSERT tb(name)
      SELECT TOP 100
      name
      FROM syscolumns
      GO
      
      2. 模拟第1个用户
      -- 查询窗口发出下面的查询语句
      BEGIN TRAN
       -- 事务不提交或者回滚, 以保持锁不释放
      SET ROWCOUNT 20
      SELECT *
      FROM tb WITH(UPDLOCK, READPAST)
       -- UPDLOCK 让锁保留到事务结束, READPAST 跳过已经锁定的数据
      
      3. 模拟第2个用户(语句与第1个用户一样,只是在另一个连接中执行)
      -- 查询窗口发出下面的查询语句
      BEGIN TRAN
       -- 事务不提交或者回滚, 以保持锁不释放
      SET ROWCOUNT 20
      SELECT *
      FROM tb WITH(UPDLOCK, READPAST)
       -- UPDLOCK 让锁保留到事务结束, READPAST 跳过已经锁定的数据
      
      4. 结果
      你会看到
      查询窗口1列出了前20条数据
      查询窗口1列出了21-40条数据 

    使用sp_Lock查看结果

    create table #temp(
     spid int,
     dbid int,
     objid int,
     IndID int,
     Type varchar(3),
     resouse varchar(20),
     Mode varchar(5),
     Status varchar(5)
    )
    insert #temp exec sp_lock @@spid
    select spid,db_name(dbid) as 数据库,
    object_name(objid) as 对象,
    索引 = (select name from sysindexes where id=objid and indid=t.indid),
    Type,Resouse,Mode,Status from #temp t where dbid>5

    drop table #temp

    select @@version

  • 相关阅读:
    自定义博客园JS插件
    SpringBoot 常见问题记录
    SpringBoot(十)-- 整合MyBatis
    SpringBoot(九)-- SpringBoot JDBC
    SpringBoot(八)-- 日志
    SpringBoot(七)-- 启动加载数据
    Java设计模式(14)责任链模式(Chain of Responsibility模式)
    Java设计模式(13)模板模式(Template模式)
    Java设计模式(12)迭代模式(Iterator模式)
    Java设计模式(11)外观模式(Facade模式)
  • 原文地址:https://www.cnblogs.com/zyizyizyi/p/2497851.html
Copyright © 2011-2022 走看看