zoukankan      html  css  js  c++  java
  • 蛙蛙推荐:多进程多线程访问数据库

    蛙蛙推荐:多进程多线程访问数据库

    如何让多进程多线程访问数据库,而不会选择相同的数据,这在设计分布式程序的时候经常用到,多台机器的多个进程,每个进程都有多个线程,每个线程要从数据库里取数据来处理,要实现不能漏取数据,也不能重复取数据,这里给出答案

    创建一个数据表,如下,一个自增列,一个表示rss链接地址

    CREATE TABLE [dbo].[Rss_RssSources](
     
    [SourceId] [int] IDENTITY(1,1NOT NULL,
     
    [Link] [varchar](1024NOT NULL
    ON [PRIMARY] 

    先放1w条数据

    declare @i int
    set @i = 1
    while @i <10000
    begin
     
    select @i = @i +1
     
    insert into [Rss_RssSources] values(newid())
    end 

    再创建一个锁表,一个字段表示是否已经锁定的资源,另一个表示已经读取的rss源的最大id

    create table Rss_RssSourceLock
    (
    IsLock 
    bit,
    MaxSourceId 
    int
    )

    初始化数据

    insert into Rss_RssSourceLock values (0,0

    下面我们要设计一个存储过程,让这个存储过程每次返回10个rss源,知道返回所有的rss源,要求无遗漏,无重复返回。如下

    CREATE PROCEDURE [dbo].[USP_GetRssSources]
    AS
    BEGIN
    if exists(select * from Rss_RssSourceLock with(READPAST) where IsLock = 0)
    begin
     
    declare @select_count int
     
    begin tran
      
    update Rss_RssSourceLock set IsLock = 1

      
    if object_id('tempdb..#t'is not null  
       
    drop table #t

      
    select top 10 a.* into #t from [Rss_RssSources] as a
      
    inner join Rss_RssSourceLock as b
      
    on a.SourceId > b.MaxSourceId
      
    order by a.[SourceId]

      
    select @select_count = count(*from #t

      
    update Rss_RssSourceLock set IsLock = 0,MaxSourceId = MaxSourceId + @select_count

      
    select * from #t
     
    commit tran
    end
    END

    1、如果锁表里显示没有进程正在读取rss源(IsLock = 0),那么就返回从最大的rss源id往后的10个rss源,否则返回空。
    2、用with(READPAST)表示忽略锁住的行,如果另一个进程正在执行update Rss_RssSourceLock的语句,并且在事务提交前,update语句会锁住这些要更新的行,而Rss_RssSourceLock表就一行数 据,这时候select Rss_RssSourceLock表并且忽略被锁的行肯定是没数据的,所以本次存储过程执行会返回空。
    3、begin tran和commit tran保证了即使本次存储过程出错,也不会让Rss_RssSourceLock表处于IsLock = 1的脏数据状态,如果处于这种状态,后面的进程执行存储过程就永远也返回不了数据了。
    4、因为有时候一次选取的记录可能不够10条,所以这里用了个临时表来暂存记录,再算出来选取的条数,最后更新Rss_RssSourceLock表的MaxSourceId字段。但用临时表肯定会增加数据库的压力,这里不知道用表变量是不是会改善性能,暂时先这样了。
    5、应用里调用这个存储过程,如果返回了数据,就进行处理,如果没返回数据,就sleep几秒才执行,直到返回数据。

    我测试了一下,应该没问题,俺是数据库菜鸟,有高手的话给指点指点有没有隐患和bug
    相关链接:
    关于sqlserver锁的一点儿讨论
    http://topic.csdn.net/t/20061127/12/5187714.html#

  • 相关阅读:
    数据库字段太多,批量快速建立实体类方法(适合大量字段建立实体类)
    SQL service 中的 ”输入SQL命令窗口“ 打开了 “属性界面” 回到 ”输入SQL命令窗口“
    计算机软件编程英语词汇集锦
    编程常用英语词汇
    svn上传和下载项目
    当启动tomcat时出现tomcat setting should be set in tomcat preference page
    Implicit super constructor Object() is undefined for default constructor. Must define an explicit constructor
    eclipse中选中一个单词 其他相同的也被选中 怎么设置
    Spring Boot的@SpringBootApplication无法引入的问题
    最全的SpringCloud视频教程
  • 原文地址:https://www.cnblogs.com/smallfa/p/1161769.html
Copyright © 2011-2022 走看看