Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 379|回复: 0

解决多线程调用sql存储过程问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-17 07:53:28 | 显示全部楼层 |阅读模式
    • 场景:

    我们程序现在改成多线程了,我现在需要把临时表中的数据给插入到TABLE_M中,但这时候可能其他的线程也在插入,我就不能用之前我们的方案了(select max(oid) from Tuning.TABLE_M。。。,之后去维护主子表关系,改掉TABLE_M的OID的自增属性,插入,之后再添加上自增属性。。。。。。)

    我现在是想这样操作:

    1,)先插入把临时数据插入到TABLE_M(OID是自增的)中(Insert Into ….select …),我之后获取 select Scope_Identity() as @MaxTABLE_MOID,之后根据这个@MaxTABLE_MOID去修改临时表中的TABLE_MOID.

    1.1,)(1,)这种方案会不会出现以下问题:

    A线程, 1-10 共10条记录,

    B 线程,1-10 共10条记录 

    A线程插入的时候,

    B线程也在再插入 

    A线程 与 B线程是交互的插入,A线程插入一条,B线程插入一条 

    运行起来像这样:

    比如 此时TABLE_M的OID为 100 

    A线程插入第一条 TABLE_M的OID变为 101

    B线程插入第一条 TABLE_M的OID变为 102 

    当我A线程插入完的时候,我A线程最后一条记录插入的OID为 120 

    这时候我的Temp 要到这个120 去修改字表关系 

    TABLE_M(OID=120) 是A 插入的没问题 

    TABLE_M(OID=119)是B插入的,这时却关联到了A线程对应的临时表的第9条记录 

    悲哀!!!

    1.2,)我们是不是要在插入的时候使用With(lock)

    2,)我还有一种想法,就是先插入完成后,根据条件查询出该批数据插入TABLE_M的生成的OID,之后这些OID去和temp匹配(按照顺序匹配,因为插入temp肯定是有序的插入),之后修改temp中的TABLE_MOID,这样就可以把子数据插入到TABLE_M_LteCell,TABLE_M_GsmCell,TABLE_M_TdsCell中。

    • DBA提供解决方案

    我们可以单独做一个表来进行OID自增的维护,可以暂时称为MAX_OID表。最简单的方式是里面仅仅记录:当前最大的OID。 

        这样我们在做多线程操作的时候遵循以下步骤 

        1. 取得MAX_OID表中的值,这样就可以获得自增的起始序列号‍

        2. 获得此次插入时候的临时表的最大行数。不要使用select count(1) from table,使用如下语句,可以获得最大的性能。

            直接获取表行数sql语句:

            select sum(row_count)

            from sys.dm_db_partition_stats

            where index_id<1 and object_id=object_id('表名')

        3. 使用max_oid+临时表的表行数,可以得到将临时表插入到主表之后,主表未来最大的MAXOID号

        4. 更新MAX_OID表。将表内数据改为:‍max_oid+临时表的表行数‍ 

        特别注意:为了保证事务一致性,上述步骤需要在一个事务中完成,需要以下语句 

        SET XACT_ABORT ON

        begin tran

             执行的sql语句(即上面1-4的逻辑操作)

        commit 

        以上四个步骤虽然文字上比较啰嗦,但是实际操作会非常快。使用的全是系统表来读取,肯定是在毫秒级别,不会影响性能。

        这样,每个线程读取的都是MAX_OID表中的值,就不会产生冲突了。‍ 

        如下面的例子:

        目前MAX_OID 最大值为100.‍

        线程一的临时表为30行

        线程二的临时表为40行    

        线程一:

        1.读取MAX_OID 表。得到100‍

        2.获得临时表行数:30

        3.得到预测的maxoid为100+30=130

        4.将MAX_OID 更改为130.‍ 

        线程二:

        1.读取MAX_OID 表。得到130

        2.获得临时表行数:40

        3.得到预测的maxoid为130+40=170

        4.将MAX_OID 更改为170.

        注意:线程二得到的MAX_OID 一定是130,而不是100.因为线程一已经更新了这个值。且更新的过程中加锁。线程二是读取不到100这个数值的。‍ 

     这样就可以避免冲突了。

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-3 10:07 , Processed in 0.076337 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表