解决多线程调用sql存储过程问题
场景:
我们程序现在改成多线程了,我现在需要把临时表中的数据给插入到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这个数值的。
这样就可以避免冲突了。
解决多线程调用sql存储过程问题的更多相关文章
- (转载)delphi 中如何调用sql 存储过程
delphi 中如何调用sql 存储过程 使用TADOStoredProc组件,可以,给你举个例子好了 with ADOStoredProc1 do begin Close; Parameters.C ...
- C# 连接Oracle,并调用存储过程(存在返回值),C# 调用sql存储过程
1.获取Oracle表格信息 public OracleHelpers(string ConnStr) { ConnectionString = ConnStr; conn = new OracleC ...
- Dynamics CRM - 使用 C# Plugin 调用 SQL 存储过程
有时候,在 Dynamics CRM Plugin 中通过 linq 查询数据会比较慢,可以通过采用在 C# plugin 中直接调用数据库存储过程的方式来提高效率,具体过程如下: 1.新建一个存储过 ...
- C#调用sql存储过程(sqlserver,包括返回值得类型)
string strcon = "server=.;database=Myschool;uid=sa;pwd=123456"; SqlConnection sqlconn = ne ...
- 关于MVC工厂模式的增删改查sql存储过程
这里MVC中用到了反射,工厂,泛型,接口 在搭建框架的时候,除了MVC的三层以外,还有泛型的接口层和工厂层 下面是dal层调用sql存储过程,增删改查,dal层继承了接口层,实现了接口层里面的方法 1 ...
- (转)jdbc 调用 sql server 的存储过程时“该语句没有返回结果集”的解决方法
本文转载自:http://hedyn.iteye.com/blog/856040 在JDBC中调用SQL Server中的存储过程时出现如下异常: com.microsoft.sqlserver.jd ...
- SQL 语句调用这个存储过程,生成顺序编码
一直很讨厌存储过程,没想到今天帮了我大忙啊,或许会因为今天让我慢慢喜欢上存储过程吧,不多说了,切入正题 在使用数据库的时候,难免要在使用过程中进行删除的操作,如果是使用int类型的字段,令其自增长,这 ...
- C#调用SQL中的存储过程中有output参数,存储过程执行过程中返回信息
C#调用SQL中的存储过程中有output参数,类型是字符型的时候一定要指定参数的长度.不然获取到的结果总是只有第一字符.本人就是由于这个原因,折腾了很久.在此记录一下,供大家以后参考! 例如: ...
- java 调用 sql server存储过程
Transact-SQL中的存储过程,非常类似于Java语言中的方法,它可以重复调用.当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可以提高存储过程的性能. Ø ...
随机推荐
- [SHELL进阶] (转)最牛B的 Linux Shell 命令 (四)
1.查看ASCII码表 man 7 ascii 很多人初学编程都会接触到ascii码的概念,有时候为了查某个符号的ascii值,可能还得翻箱倒柜找出当年的课本?Linux Manpage里面其实包含 ...
- Unity中的协程(一)
这篇文章很不错的问题,推荐阅读英文原版: Introduction to Coroutines Scripting with Coroutines 这篇文章转自:http://blog.csdn. ...
- oracle sqlplus常用命令
登录到sqlplus sqlplus user/pwd@dbname 不登录使用 sqlplus /nolog 查看当前登录用户 show user; 更改用户密码 ALTER USER USER I ...
- PHP学习(一)----变量及字符串
PHP中的变量: 1. 定义:$符号来定义变量 2. 说明: (1)PHP弱语言,定义变量的时候不用声明类型,但是并不代表PHP没有数据类型 (2)变量名是区分大小写的,只能是数字,字母或者下划线 ( ...
- MillWheel: Fault-Tolerant Stream Processing at Internet Scale
http://static.googleusercontent.com/media/research.google.com/zh-CN//pubs/archive/41378.pdf 为什么要做M ...
- 【Android开发学习笔记】【高级】【随笔】插件化——资源加载
前言 上一节我们针对插件最基本的原理进行了一个简单的demo实现,但是由于插件的Context对象被宿主所接管,因此无法加载插件程序的资源.那么如何解决这个问题捏? 有人提出这样的方案:将apk中的资 ...
- JQuery源码之“名叫extend的继承”
提起JS中的继承很多”大神“们都会提起call,apply,单纯的对象赋值继承,以及原型链继承等众多的方式以及它们的不足之处,而且还会不时的把一些面向对象的设计模式”团团“的带出来,可谓是厉害非常啊! ...
- Redis Sentinel高可用配置及C#访问
本文环境如下: 操作系统:ubuntu-14.04.1-desktop-amd64 Redis:2.8.19 如果使用虚拟机则将每台的网络设置为桥接,否则他们之间能连上,局域网连不上. 系统设计如图: ...
- 使用多种客户端消费WCF RestFul服务(三)——.net4.5篇
.net 4.5篇 在.net 4.5下面微软提供了System.Net.Http.dll可以非常方便的使用HTTP请求(其实是用来支持Asp.Net Web Api的,不过我们可以拿过来用) 服务仍 ...
- php练习:给指定商品添加特殊效果
老板说: 我只要在文本框填1|3 ,那第1和第3个商品都要标注! 思考过程: 有了重要信息1和3,而循环商品时$key按顺序自动递增,那么只要key和信息匹配的话,就判断商品添加标注,这个可以把位置信 ...