sql server 大数据量并发插入问题

imlmy 2013-11-21 03:49:32
开发了一个设备采集监控系统。其中设备数据项有2000多个,保存在sql server2008中。存储方案是针对每个设备创建一个单独的数据库,里面建立多个数据表,把数据项分表存储。在主数据库中提供插入数据存储过程,将传入的数据插入到对应数据库中。
测试中发现,使用ado连接数据库,当有60个线程同时插入60个设备的数据,同时开30个线程进行查询。每个线程都采用独立的连接,查询的时候将数据表设置为nolock。但是还是会出现查询超时已过期问题。想问一下这是由于sql server本身处理不过来导致的,还是ado的问题。
同时单独运行一个线程插入时速度还可以,但60个线程同时插入的时候,单个线程的插入速度就降到原来的1/20。所有线程调用的是同一个存储过程,但是插入数据库不同。
...全文
2169 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
人鱼传说 2013-12-15
  • 打赏
  • 举报
回复
楼主的方案有很大问题,60个设备+一个主数据库+60个设备数据库,你服务器再牛,存储过程也只能一个个的将60个设备数据依先后次序写入相应的设备数据库,主数据库是写入的性能瓶颈,现在60个设备以内写入可能感觉不到慢,是因为设备数据库数据量还不大,一但大起来,不用到60个设备就能感觉到慢了,所以我说你的方案设计是有问题的,如何解决:架构改为N设备对N数据库,如体做法是: 修改你的数据采集程序,由程序线程自动通过设备号来判断应该连接哪个数据库(ado连接字符串可以确定),跳过数据写入瓶颈,调用的存储过程自然就是相应的设备数据库的存储过程,这样就能真正的做到并发写入,磁盘阵列IO性能得到发挥.
  • 打赏
  • 举报
回复
引用 28 楼 imlmy 的回复:
多线程并发查询,select语句被自身给阻塞了,这个不太好理解。查询sysprocesses,发现spid和blocked相同,cmd为select,waitresource为ACCESS_METHODS_DATASET_PARENT。waittime达到5763ms。select的表有增加nolock标志,不过这个是针对插入数据的,应该没有关系。
这个是latch,也就是闩锁等待:ACCESS_METHODS_DATASET_PARENT 用于同步在并行操作期间对父数据集进行的子数据集访问。 也就是你的select语句,采用了并行的执行计划,在执行时,需要同步这些并行操作,所以就出现了等待。 比如,一共处理n条数据,给2个线程处理,每个n/2条,但是有一个线程处理的快,一个慢,所以快的那个就得等着慢的那个,所以就出现了这种等待。
hgwyl 2013-11-29
  • 打赏
  • 举报
回复
怎么觉得数据库的设计显得怪怪的…… 设备数据项有2000多个 如果达到这个级别,硬件设备才是最大的瓶颈吧? 如果就是一台服务器,拖那么多库,还是并发,怎么都快不起来吧…… 也许你可以看看这个大神问的。也是搞监控的。 猛戳这个传送门:海量数据,每天5T,数据至少保存1年,使用啥数据库来解决呢?
imlmy 2013-11-29
  • 打赏
  • 举报
回复
多线程并发查询,select语句被自身给阻塞了,这个不太好理解。查询sysprocesses,发现spid和blocked相同,cmd为select,waitresource为ACCESS_METHODS_DATASET_PARENT。waittime达到5763ms。select的表有增加nolock标志,不过这个是针对插入数据的,应该没有关系。
imlmy 2013-11-29
  • 打赏
  • 举报
回复
存储过程中使用游标导致的阻塞主要是由于对tempdb的并发读写,waitresource为2:1:1或2:1:3。 http://support.microsoft.com/kb/328551/zh-cn
  • 打赏
  • 举报
回复
引用 25 楼 imlmy 的回复:
[quote=引用 23 楼 yupeigu 的回复:] [quote=引用 21 楼 imlmy 的回复:] [quote=引用 20 楼 yupeigu 的回复:] [quote=引用 19 楼 imlmy 的回复:] [quote=引用 18 楼 yupeigu 的回复:] [quote=引用 16 楼 imlmy 的回复:] [quote=引用 14 楼 yupeigu 的回复:] [quote=引用 13 楼 imlmy 的回复:] [quote=引用 4 楼 jwwyqs 的回复:] 60个设备也就是60个数据库通过一个存储过程同时插入数据啊,太恐怖了,估计内存资源也会很吃紧的
我觉得单个存储过程被多个连接并发调用,只要使用的资源不存在排他锁问题,应该可以。不过cpu却是占用很高,几乎满了。我主要是在想是由于cpu处理不过来导致的,还是由于并发插入存在锁的问题。因为我并发插入的数据是在不同的数据库中,只是调用的存储过程是同一个。[/quote] 运行下面的语句,看看有没有阻塞的问题:
select *
from sys.sysprocesses
where blocked <> 0
[/quote] 查到了,大部分是打开游标的阻塞。因为存储过程里面有一个操作是用游标遍历一个数据表的数据,构建sql语句。是不是游标会自动加锁。[/quote] 你可以考虑不用游标,反正是2008,可以考虑用row_number函数,来变量表中的每一行数据,这样至少不会导致严重的阻塞问题,而且速度更快。 可以这样:


declare @i int;  
declare @count int;  
  
set @i = 1  
set @count = (select count(*) from 表);  
         
while @i <= @count  
begin  
   ;with t  
   as  
   (  
   select *,  
          row_number() over(order by @@servername) as rownum  
   from 表  
   )  
      
   select 你的变量1 = (select 字段 from 表 where rownum = @i),
          你的变量2 = ...
   
   --用变量构造动态语句
           
   set @i = @i + 1  
end
[/quote] 多谢大神。不过我看网上通过rownumber来遍历数据表很多采用了临时表,就是把查询数据放到临时表,再遍历临时表。这样是不是为了避免锁的问题。但是将数据插入临时表,再删除临时表又会减低一定的效率。[/quote] 哦 不会,临时表的开销很小的,如果数据较少,是直接放到内存中,的只有数据比较大的时候,才会放到硬盘上。 另外,临时表还支持创建索引。[/quote] 多谢。用临时表row_number代替游标进行遍历,减少了打开游标的阻塞问题。另外使用临时表会对系统表sysprocesses等进行加锁,所以有时候也可能导致阻塞,但是问题不大。目前我是使用了临时表变量。不过测试的时候发现还是存在一些超时已过期的问题。主要是在执行存储过程的时候,这个存储过程实现的功能就是构建插入语句插入到对应数据库中。但是在出现超时问题的时候查询阻塞情况,发现基本没有阻塞操作,或者阻塞的时间很短。出现超时的时候就会连续出现多次。还会有什么问题会导致这个存储过程超时呢。[/quote] 其实出现超时,一个是因为阻塞问题,另一个就是你语句的执行速度,由于你的语句大部分是插入操作,那么在插入大量数据的时候,是把数据插入到某一个数据页中的,一个页大小时8K,当这个页中的数据已经很多的时候,比如8K中,已经占用了7k了,那么这个时候再次插入多条记录,那么这个数据页可能就放不下这些记录了,于是sql server需要进行页分裂, 也就是page split,就是新增一个数据页,然后把原来的一页的内容,一般是平均分到这2页中,然后再把数据插入进去。 所以,这个时候可以考虑,先在数据页中,预留一部分空间,这个可以通过重建索引,然后指定fillfactor = 50,这样就可以让页中有一半是空闲空间,于是下次再次插入时,就会减少页的分裂。 随着插入的数据越来越多,这些页的填充程度,也越来越高,可能上升到80,那么这个时候,我们可以再次重建聚集索引,指定这个fillfactor = 50,于是数据再次重新分布。[/quote] 之前只是查看阻塞情况,忽视了对比效率。今天测试发现使用游标的效率比使用row_number高。使用游标的方式是open cursor for select ....... from table1,table2 where....... 而使用row_number的方式是将table1,table2的查询结果以及row_number存入临时表#temptable。然后通过
select @max = count(*) from #temptable
set @i = 1
while @i < @max
begin
    select ....... from #temptable where rownum=@i
    set @i = @i+1
end
通过这种方式进行遍历,发现效率比游标低很多,后来将#temptable的rownum设为主键,效率提高不少,但是还是比游标遍历低。 是不是我使用的方式有问题。 网上有人提到说row_number主要用产生顺序指令,http://social.msdn.microsoft.com/Forums/en-US/bb30f8ed-8ca3-448e-8f46-f55a7246b865/cursor-rownumber[/quote] 看了文章的连接,结合你的实际测试情况,看来用row_number的效率也不是太好。 要不帮你看看,你的存储过程到底是怎么写的,能不能优化吧,我加你关注了,可以发私信。
imlmy 2013-11-28
  • 打赏
  • 举报
回复
引用 23 楼 yupeigu 的回复:
[quote=引用 21 楼 imlmy 的回复:] [quote=引用 20 楼 yupeigu 的回复:] [quote=引用 19 楼 imlmy 的回复:] [quote=引用 18 楼 yupeigu 的回复:] [quote=引用 16 楼 imlmy 的回复:] [quote=引用 14 楼 yupeigu 的回复:] [quote=引用 13 楼 imlmy 的回复:] [quote=引用 4 楼 jwwyqs 的回复:] 60个设备也就是60个数据库通过一个存储过程同时插入数据啊,太恐怖了,估计内存资源也会很吃紧的
我觉得单个存储过程被多个连接并发调用,只要使用的资源不存在排他锁问题,应该可以。不过cpu却是占用很高,几乎满了。我主要是在想是由于cpu处理不过来导致的,还是由于并发插入存在锁的问题。因为我并发插入的数据是在不同的数据库中,只是调用的存储过程是同一个。[/quote] 运行下面的语句,看看有没有阻塞的问题:
select *
from sys.sysprocesses
where blocked <> 0
[/quote] 查到了,大部分是打开游标的阻塞。因为存储过程里面有一个操作是用游标遍历一个数据表的数据,构建sql语句。是不是游标会自动加锁。[/quote] 你可以考虑不用游标,反正是2008,可以考虑用row_number函数,来变量表中的每一行数据,这样至少不会导致严重的阻塞问题,而且速度更快。 可以这样:


declare @i int;  
declare @count int;  
  
set @i = 1  
set @count = (select count(*) from 表);  
         
while @i <= @count  
begin  
   ;with t  
   as  
   (  
   select *,  
          row_number() over(order by @@servername) as rownum  
   from 表  
   )  
      
   select 你的变量1 = (select 字段 from 表 where rownum = @i),
          你的变量2 = ...
   
   --用变量构造动态语句
           
   set @i = @i + 1  
end
[/quote] 多谢大神。不过我看网上通过rownumber来遍历数据表很多采用了临时表,就是把查询数据放到临时表,再遍历临时表。这样是不是为了避免锁的问题。但是将数据插入临时表,再删除临时表又会减低一定的效率。[/quote] 哦 不会,临时表的开销很小的,如果数据较少,是直接放到内存中,的只有数据比较大的时候,才会放到硬盘上。 另外,临时表还支持创建索引。[/quote] 多谢。用临时表row_number代替游标进行遍历,减少了打开游标的阻塞问题。另外使用临时表会对系统表sysprocesses等进行加锁,所以有时候也可能导致阻塞,但是问题不大。目前我是使用了临时表变量。不过测试的时候发现还是存在一些超时已过期的问题。主要是在执行存储过程的时候,这个存储过程实现的功能就是构建插入语句插入到对应数据库中。但是在出现超时问题的时候查询阻塞情况,发现基本没有阻塞操作,或者阻塞的时间很短。出现超时的时候就会连续出现多次。还会有什么问题会导致这个存储过程超时呢。[/quote] 其实出现超时,一个是因为阻塞问题,另一个就是你语句的执行速度,由于你的语句大部分是插入操作,那么在插入大量数据的时候,是把数据插入到某一个数据页中的,一个页大小时8K,当这个页中的数据已经很多的时候,比如8K中,已经占用了7k了,那么这个时候再次插入多条记录,那么这个数据页可能就放不下这些记录了,于是sql server需要进行页分裂, 也就是page split,就是新增一个数据页,然后把原来的一页的内容,一般是平均分到这2页中,然后再把数据插入进去。 所以,这个时候可以考虑,先在数据页中,预留一部分空间,这个可以通过重建索引,然后指定fillfactor = 50,这样就可以让页中有一半是空闲空间,于是下次再次插入时,就会减少页的分裂。 随着插入的数据越来越多,这些页的填充程度,也越来越高,可能上升到80,那么这个时候,我们可以再次重建聚集索引,指定这个fillfactor = 50,于是数据再次重新分布。[/quote] 之前只是查看阻塞情况,忽视了对比效率。今天测试发现使用游标的效率比使用row_number高。使用游标的方式是open cursor for select ....... from table1,table2 where....... 而使用row_number的方式是将table1,table2的查询结果以及row_number存入临时表#temptable。然后通过
select @max = count(*) from #temptable
set @i = 1
while @i < @max
begin
    select ....... from #temptable where rownum=@i
    set @i = @i+1
end
通过这种方式进行遍历,发现效率比游标低很多,后来将#temptable的rownum设为主键,效率提高不少,但是还是比游标遍历低。 是不是我使用的方式有问题。 网上有人提到说row_number主要用产生顺序指令,http://social.msdn.microsoft.com/Forums/en-US/bb30f8ed-8ca3-448e-8f46-f55a7246b865/cursor-rownumber
shoppo0505 2013-11-26
  • 打赏
  • 举报
回复
1. 去除游标的使用。 2. 新装个SSD,把数据库文件安到SSD上,再挂在server上,不需要更改其他任何设置。
  • 打赏
  • 举报
回复
引用 21 楼 imlmy 的回复:
[quote=引用 20 楼 yupeigu 的回复:] [quote=引用 19 楼 imlmy 的回复:] [quote=引用 18 楼 yupeigu 的回复:] [quote=引用 16 楼 imlmy 的回复:] [quote=引用 14 楼 yupeigu 的回复:] [quote=引用 13 楼 imlmy 的回复:] [quote=引用 4 楼 jwwyqs 的回复:] 60个设备也就是60个数据库通过一个存储过程同时插入数据啊,太恐怖了,估计内存资源也会很吃紧的
我觉得单个存储过程被多个连接并发调用,只要使用的资源不存在排他锁问题,应该可以。不过cpu却是占用很高,几乎满了。我主要是在想是由于cpu处理不过来导致的,还是由于并发插入存在锁的问题。因为我并发插入的数据是在不同的数据库中,只是调用的存储过程是同一个。[/quote] 运行下面的语句,看看有没有阻塞的问题:
select *
from sys.sysprocesses
where blocked <> 0
[/quote] 查到了,大部分是打开游标的阻塞。因为存储过程里面有一个操作是用游标遍历一个数据表的数据,构建sql语句。是不是游标会自动加锁。[/quote] 你可以考虑不用游标,反正是2008,可以考虑用row_number函数,来变量表中的每一行数据,这样至少不会导致严重的阻塞问题,而且速度更快。 可以这样:


declare @i int;  
declare @count int;  
  
set @i = 1  
set @count = (select count(*) from 表);  
         
while @i <= @count  
begin  
   ;with t  
   as  
   (  
   select *,  
          row_number() over(order by @@servername) as rownum  
   from 表  
   )  
      
   select 你的变量1 = (select 字段 from 表 where rownum = @i),
          你的变量2 = ...
   
   --用变量构造动态语句
           
   set @i = @i + 1  
end
[/quote] 多谢大神。不过我看网上通过rownumber来遍历数据表很多采用了临时表,就是把查询数据放到临时表,再遍历临时表。这样是不是为了避免锁的问题。但是将数据插入临时表,再删除临时表又会减低一定的效率。[/quote] 哦 不会,临时表的开销很小的,如果数据较少,是直接放到内存中,的只有数据比较大的时候,才会放到硬盘上。 另外,临时表还支持创建索引。[/quote] 多谢。用临时表row_number代替游标进行遍历,减少了打开游标的阻塞问题。另外使用临时表会对系统表sysprocesses等进行加锁,所以有时候也可能导致阻塞,但是问题不大。目前我是使用了临时表变量。不过测试的时候发现还是存在一些超时已过期的问题。主要是在执行存储过程的时候,这个存储过程实现的功能就是构建插入语句插入到对应数据库中。但是在出现超时问题的时候查询阻塞情况,发现基本没有阻塞操作,或者阻塞的时间很短。出现超时的时候就会连续出现多次。还会有什么问题会导致这个存储过程超时呢。[/quote] 其实出现超时,一个是因为阻塞问题,另一个就是你语句的执行速度,由于你的语句大部分是插入操作,那么在插入大量数据的时候,是把数据插入到某一个数据页中的,一个页大小时8K,当这个页中的数据已经很多的时候,比如8K中,已经占用了7k了,那么这个时候再次插入多条记录,那么这个数据页可能就放不下这些记录了,于是sql server需要进行页分裂, 也就是page split,就是新增一个数据页,然后把原来的一页的内容,一般是平均分到这2页中,然后再把数据插入进去。 所以,这个时候可以考虑,先在数据页中,预留一部分空间,这个可以通过重建索引,然后指定fillfactor = 50,这样就可以让页中有一半是空闲空间,于是下次再次插入时,就会减少页的分裂。 随着插入的数据越来越多,这些页的填充程度,也越来越高,可能上升到80,那么这个时候,我们可以再次重建聚集索引,指定这个fillfactor = 50,于是数据再次重新分布。
imlmy 2013-11-26
  • 打赏
  • 举报
回复
会不会是设备数据库文件大小增长问题,不过我目前已经设置成1M的增长
imlmy 2013-11-26
  • 打赏
  • 举报
回复
引用 20 楼 yupeigu 的回复:
[quote=引用 19 楼 imlmy 的回复:] [quote=引用 18 楼 yupeigu 的回复:] [quote=引用 16 楼 imlmy 的回复:] [quote=引用 14 楼 yupeigu 的回复:] [quote=引用 13 楼 imlmy 的回复:] [quote=引用 4 楼 jwwyqs 的回复:] 60个设备也就是60个数据库通过一个存储过程同时插入数据啊,太恐怖了,估计内存资源也会很吃紧的
我觉得单个存储过程被多个连接并发调用,只要使用的资源不存在排他锁问题,应该可以。不过cpu却是占用很高,几乎满了。我主要是在想是由于cpu处理不过来导致的,还是由于并发插入存在锁的问题。因为我并发插入的数据是在不同的数据库中,只是调用的存储过程是同一个。[/quote] 运行下面的语句,看看有没有阻塞的问题:
select *
from sys.sysprocesses
where blocked <> 0
[/quote] 查到了,大部分是打开游标的阻塞。因为存储过程里面有一个操作是用游标遍历一个数据表的数据,构建sql语句。是不是游标会自动加锁。[/quote] 你可以考虑不用游标,反正是2008,可以考虑用row_number函数,来变量表中的每一行数据,这样至少不会导致严重的阻塞问题,而且速度更快。 可以这样:


declare @i int;  
declare @count int;  
  
set @i = 1  
set @count = (select count(*) from 表);  
         
while @i <= @count  
begin  
   ;with t  
   as  
   (  
   select *,  
          row_number() over(order by @@servername) as rownum  
   from 表  
   )  
      
   select 你的变量1 = (select 字段 from 表 where rownum = @i),
          你的变量2 = ...
   
   --用变量构造动态语句
           
   set @i = @i + 1  
end
[/quote] 多谢大神。不过我看网上通过rownumber来遍历数据表很多采用了临时表,就是把查询数据放到临时表,再遍历临时表。这样是不是为了避免锁的问题。但是将数据插入临时表,再删除临时表又会减低一定的效率。[/quote] 哦 不会,临时表的开销很小的,如果数据较少,是直接放到内存中,的只有数据比较大的时候,才会放到硬盘上。 另外,临时表还支持创建索引。[/quote] 多谢。用临时表row_number代替游标进行遍历,减少了打开游标的阻塞问题。另外使用临时表会对系统表sysprocesses等进行加锁,所以有时候也可能导致阻塞,但是问题不大。目前我是使用了临时表变量。不过测试的时候发现还是存在一些超时已过期的问题。主要是在执行存储过程的时候,这个存储过程实现的功能就是构建插入语句插入到对应数据库中。但是在出现超时问题的时候查询阻塞情况,发现基本没有阻塞操作,或者阻塞的时间很短。出现超时的时候就会连续出现多次。还会有什么问题会导致这个存储过程超时呢。
  • 打赏
  • 举报
回复
引用 16 楼 imlmy 的回复:
[quote=引用 14 楼 yupeigu 的回复:] [quote=引用 13 楼 imlmy 的回复:] [quote=引用 4 楼 jwwyqs 的回复:] 60个设备也就是60个数据库通过一个存储过程同时插入数据啊,太恐怖了,估计内存资源也会很吃紧的
我觉得单个存储过程被多个连接并发调用,只要使用的资源不存在排他锁问题,应该可以。不过cpu却是占用很高,几乎满了。我主要是在想是由于cpu处理不过来导致的,还是由于并发插入存在锁的问题。因为我并发插入的数据是在不同的数据库中,只是调用的存储过程是同一个。[/quote] 运行下面的语句,看看有没有阻塞的问题:
select *
from sys.sysprocesses
where blocked <> 0
[/quote] 查到了,大部分是打开游标的阻塞。因为存储过程里面有一个操作是用游标遍历一个数据表的数据,构建sql语句。是不是游标会自动加锁。[/quote] 你可以考虑不用游标,反正是2008,可以考虑用row_number函数,来变量表中的每一行数据,这样至少不会导致严重的阻塞问题,而且速度更快。 可以这样:


declare @i int;  
declare @count int;  
  
set @i = 1  
set @count = (select count(*) from 表);  
         
while @i <= @count  
begin  
   ;with t  
   as  
   (  
   select *,  
          row_number() over(order by @@servername) as rownum  
   from 表  
   )  
      
   select 你的变量1 = (select 字段 from 表 where rownum = @i),
          你的变量2 = ...
   
   --用变量构造动态语句
           
   set @i = @i + 1  
end
  • 打赏
  • 举报
回复
引用 16 楼 imlmy 的回复:
[quote=引用 14 楼 yupeigu 的回复:] [quote=引用 13 楼 imlmy 的回复:] [quote=引用 4 楼 jwwyqs 的回复:] 60个设备也就是60个数据库通过一个存储过程同时插入数据啊,太恐怖了,估计内存资源也会很吃紧的
我觉得单个存储过程被多个连接并发调用,只要使用的资源不存在排他锁问题,应该可以。不过cpu却是占用很高,几乎满了。我主要是在想是由于cpu处理不过来导致的,还是由于并发插入存在锁的问题。因为我并发插入的数据是在不同的数据库中,只是调用的存储过程是同一个。[/quote] 运行下面的语句,看看有没有阻塞的问题:
select *
from sys.sysprocesses
where blocked <> 0
[/quote] 查到了,大部分是打开游标的阻塞。因为存储过程里面有一个操作是用游标遍历一个数据表的数据,构建sql语句。是不是游标会自动加锁。[/quote] 是的,游标不仅慢,而且可能锁住表的所有数据,造成严重的阻塞问题。
imlmy 2013-11-22
  • 打赏
  • 举报
回复
引用 14 楼 yupeigu 的回复:
[quote=引用 13 楼 imlmy 的回复:] [quote=引用 4 楼 jwwyqs 的回复:] 60个设备也就是60个数据库通过一个存储过程同时插入数据啊,太恐怖了,估计内存资源也会很吃紧的
我觉得单个存储过程被多个连接并发调用,只要使用的资源不存在排他锁问题,应该可以。不过cpu却是占用很高,几乎满了。我主要是在想是由于cpu处理不过来导致的,还是由于并发插入存在锁的问题。因为我并发插入的数据是在不同的数据库中,只是调用的存储过程是同一个。[/quote] 运行下面的语句,看看有没有阻塞的问题:
select *
from sys.sysprocesses
where blocked <> 0
[/quote] 查到了,大部分是打开游标的阻塞。因为存储过程里面有一个操作是用游标遍历一个数据表的数据,构建sql语句。是不是游标会自动加锁。
火拼阿三 2013-11-22
  • 打赏
  • 举报
回复
楼上的都牛X的一塌糊涂。。。学习下。。。
  • 打赏
  • 举报
回复
引用 13 楼 imlmy 的回复:
[quote=引用 4 楼 jwwyqs 的回复:] 60个设备也就是60个数据库通过一个存储过程同时插入数据啊,太恐怖了,估计内存资源也会很吃紧的
我觉得单个存储过程被多个连接并发调用,只要使用的资源不存在排他锁问题,应该可以。不过cpu却是占用很高,几乎满了。我主要是在想是由于cpu处理不过来导致的,还是由于并发插入存在锁的问题。因为我并发插入的数据是在不同的数据库中,只是调用的存储过程是同一个。[/quote] 运行下面的语句,看看有没有阻塞的问题:
select *
from sys.sysprocesses
where blocked <> 0
imlmy 2013-11-22
  • 打赏
  • 举报
回复
引用 4 楼 jwwyqs 的回复:
60个设备也就是60个数据库通过一个存储过程同时插入数据啊,太恐怖了,估计内存资源也会很吃紧的
我觉得单个存储过程被多个连接并发调用,只要使用的资源不存在排他锁问题,应该可以。不过cpu却是占用很高,几乎满了。我主要是在想是由于cpu处理不过来导致的,还是由于并发插入存在锁的问题。因为我并发插入的数据是在不同的数据库中,只是调用的存储过程是同一个。
imlmy 2013-11-22
  • 打赏
  • 举报
回复
目前的数据库设计是这样的,有一个主数据库,里面有设备类型描述表,提供一个创建设备的存储过程,在主数据库的设备表中增加一条记录,同时根据设备类型描述创建一个新的设备数据库,里面创建设备数据表。设备数据库就只有数据表,没有存储过程。同时主数据库提供一个存储过程用于插入数据,这个存储过程用于构建sql语句,use到对应的设备数据库,执行插入语句。主数据库和设备数据库都在一个实例里面。 之前这样设计是考虑兼容扩展多种不同的设备,如果添加新的设备,只需要在主数据库的设备类型描述表中增加对应设备数据的描述就行。而且应用程序调用也比较简单,不用考虑数据库结构,只需要调用存储过程接口就行。 之前一直提示查询超时的问题找到了,是由于查询数据的范围包含正在插入的数据,所以导致等待锁超时。
  • 打赏
  • 举报
回复
都分数据库了,为什么还要使用同一个存储过程来往不同数据库里写数据? 插入数据的话会在page的级别产生IX锁,这个是不影响查询的。 如果表有聚集索引,会在key级别产生X锁,所谓X锁就是排他锁。 也就是说如果事务T在某个页面或者表上加了X锁,那么别的事务是不能够访问这个页面或者表的。
---涛声依旧--- 2013-11-22
  • 打赏
  • 举报
回复
为什么要用同一个存储过程呢? 既然是不同的连接就调用该连接的数据库中的那个存储过程了 同一台机器上哪怕用存储过程了但跨数据库了效率还是有影响的
加载更多回复(11)
本课程根据讲师十多年在世界500强外企的生产环境中的SQL Serer数据库管理和项目实施经验倾心打造。课程系统性强,知识体系完整,覆盖90%以上的企业环境下SQL Server高可用场景,课程中不仅演示详细的操作步骤,更加突出最常见的故障和问题,让学员少走“弯路”,不只是让学员学会“操作”更能让学员“操作”的规范,满满的干货分享,一些课程资料(架构图、部署规划表格等)不仅可以帮助学员掌握技能,也可以作为学员在企业生产环境中实施SQL Server高可用的配置文档、操作手册等。课程的实验环境介绍:1)全部基于微软域环境和企业版SQL Server AOAG - 95%以上的企业环境都是在域环境中,不介绍非域环境和标准版的SQL Server高可用性组,这的配置在企业中较罕见,没有实践意义,不浪费学员时间。2)相应域环境已提前部署和配置好 - 学员导入虚拟机即可开始实验,无需从零开始搭建域环境,所有实验中SQL Server均已加域,直入主题,节省大时间。3)最新的Windows Server故障转移集群(WS2016、WS2019)和最新版本的SQL ServerSQL2017、SQL2019) -  WS2016-SQL2017与WS2019-SQL2019是目前大多数企业SQL Server高可用的主要平台,基于微软产品生命周期现在一些企业也在讲早期的AOAG向这两个版本迁移,掌握这两种组合不仅让学员学会,更能学有所用。本课程为后续SQL Server进阶课程铺垫,是通向SQL Server DBA 专家的必经之路,讲师每周答疑两次。所有课程资料包括:课程PPT、架构图、部署规划表格、各类脚本学员均可下载。     
JAVA开发人员必备是HTML格式的 JavaTM 2 Platform Standard Edition 6 API 规范 本文档是 Java 2 Platform Standard Edition 6.0 的 API 规范。 请参见: 描述 Java 2 Platform 软件包 java.applet 提供创建 applet 所必需的类和 applet 用来与其 applet 上下文通信的类。 java.awt 包含用于创建用户界面和绘制图形图像的所有类。 java.awt.color 提供用于颜色空间的类。 java.awt.datatransfer 提供在应用程序之间和在应用程序内部传输数据的接口和类。 java.awt.dnd Drag 和 Drop 是一种直接操作动作,在许多图形用户界面系统中都会遇到它,它提供了一种机制,能够在两个与 GUI 中显示元素逻辑相关的实体之间传输信息。 java.awt.event 提供处理由 AWT 组件所激发的各类事件的接口和类。 java.awt.font 提供与字体相关的类和接口。 java.awt.geom 提供用于在与二维几何形状相关的对象上定义和执行操作的 Java 2D 类。 java.awt.im 提供输入方法框架所需的类和接口。 java.awt.im.spi 提供启用可以与 Java 运行时环境一起使用的输入方法开发的接口。 java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,即基于 JavaBeansTM 架构的组件。 java.beans.beancontext 提供与 bean 上下文有关的类和接口。 java.io 通过数据流、序列化和文件系统提供系统输入和输出。 java.lang 提供利用 Java 编程语言进行程序设计的基础类。 java.lang.annotation 为 Java 编程语言注释设施提供库支持。 java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供了引用对象类,支持在某种程度上与垃圾回收器之间的交互。 java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java.nio 定义作为数据容器的缓冲区,并提供其他 NIO 包的概述。 java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务提供者类。 java.nio.charset 定义用来在字节和 Unicode 字符之间转换的 charset、解码器和编码器。 java.nio.charset.spi java.nio.charset 包的服务提供者类。 java.rmi 提供 RMI 包。 java.rmi.activation 为 RMI 对象激活提供支持。 java.rmi.dgc 为 RMI 分布式垃圾回收提供了类和接口。 java.rmi.registry 提供 RMI 注册表的一个类和两个接口。 java.rmi.server 提供支持服务器端 RMI 的类和接口。 java.security 为安全框架提供类和接口。 java.security.acl 此包中的类和接口已经被 java.security 包中的类取代。 java.security.cert 提供用于解析和管理证书、证书撤消列表 (CRL) 和证书路径的类和接口。 java.security.interfaces 提供的接口用于生成 RSA Laboratory Technical Note PKCS#1 中定义的 RSA(Rivest、Shamir 和 Adleman AsymmetricCipher 算法)密钥,以及 NIST 的 FIPS-186 中定义的 DSA(数字签名算法)密钥。 java.security.spec 提供密钥规范和算法参数规范的类和接口。 java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text 包中类的服务提供者类。 java.util 包含 collection 框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。 java.util.concurrent 在并发编程中很常用的实用工具类。 java.util.concurrent.atomic 类的小工具包,支持在单个变上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序存储并获取用户和系统首选项和配置数据。 java.util.regex 用于匹配字符序列与正则表达式指定模式的类。 java.util.spi java.util 包中类的服务提供者类。 java.util.zip 提供用于读写标准 ZIP 和 GZIP 文件格式的类。 javax.accessibility 定义了用户界面组件与提供对这些组件进行访问的辅助技术之间的协定。 javax.crypto 为加密操作提供类和接口。 javax.crypto.interfaces 根据 RSA Laboratories' PKCS #3 的定义,提供 Diffie-Hellman 密钥接口。 javax.crypto.spec 为密钥规范和算法参数规范提供类和接口。 javax.imageio Java Image I/O API 的主要包。 javax.imageio.event Java Image I/O API 的一个包,用于在读取和写入图像期间处理事件的同步通知。 javax.imageio.metadata 用于处理读写元数据的 Java Image I/O API 的包。 javax.imageio.plugins.bmp 包含供内置 BMP 插件使用的公共类的包。 javax.imageio.plugins.jpeg 支持内置 JPEG 插件的类。 javax.imageio.spi 包含用于 reader、writer、transcoder 和流的插件接口以及一个运行时注册表的 Java Image I/O API 包。 javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I/O。 javax.management 提供 Java Management Extensions 的核心类。 javax.management.loading 提供实现高级动态加载的类。 javax.management.modelmbean 提供了 ModelMBean 类的定义。 javax.management.monitor 提供 monitor 类的定义。 javax.management.openmbean 提供开放数据类型和 Open MBean 描述符类。 javax.management.relation 提供 Relation Service 的定义。 javax.management.remote 对 JMX MBean 服务器进行远程访问使用的接口。 javax.management.remote.rmi RMI 连接器是供 JMX Remote API 使用的一种连接器,后者使用 RMI 将客户端请求传输到远程 MBean 服务器。 javax.management.timer 提供对 Timer MBean(计时器 MBean)的定义。 javax.naming 为访问命名服务提供类和接口。 javax.naming.directory 扩展 javax.naming 包以提供访问目录服务的功能。 javax.naming.event 在访问命名和目录服务时提供对事件通知的支持。 javax.naming.ldap 提供对 LDAPv3 扩展操作和控件的支持。 javax.naming.spi 提供一些方法来动态地插入对通过 javax.naming 和相关包访问命名和目录服务的支持。 javax.net 提供用于网络应用程序的类。 javax.net.ssl 提供用于安全套接字包的类。 javax.print 为 JavaTM Print Service API 提供了主要类和接口。 javax.print.attribute 提供了描述 JavaTM Print Service 属性的类型以及如何分类这些属性的类和接口。 javax.print.attribute.standard 包 javax.print.attribute.standard 包括特定打印属性的类。 javax.print.event 包 javax.print.event 包含事件类和侦听器接口。 javax.rmi 包含 RMI-IIOP 的用户 API。 javax.rmi.CORBA 包含用于 RMI-IIOP 的可移植性 API。 javax.rmi.ssl 通过安全套接字层 (SSL) 或传输层安全 (TLS) 协议提供 RMIClientSocketFactory 和 RMIServerSocketFactory 的实现。 javax.security.auth 此包提供用于进行验证和授权的框架。 javax.security.auth.callback 此包提供与应用程序进行交互所必需的类,以便检索信息(例如,包括用户名和密码的验证数据)或显示信息(例如,错误和警告消息)。 javax.security.auth.kerberos 此包包含与 Kerberos 网络验证协议相关的实用工具类。 javax.security.auth.login 此包提供可插入的验证框架。 javax.security.auth.spi 此包提供用于实现可插入验证模块的接口。 javax.security.auth.x500 此包包含应该用来在 Subject 中存储 X500 Principal 和 X500 Private Crendentials 的类。 javax.security.cert 为公钥证书提供类。 javax.security.sasl 包含用于支持 SASL 的类和接口。 javax.sound.midi 提供用于 MIDI(音乐乐器数字接口)数据的 I/O、序列化和合成的接口和类。 javax.sound.midi.spi 在提供新的 MIDI 设备、MIDI 文件 reader 和 writer、或音库 reader 时提供服务提供者要实现的接口。 javax.sound.sampled 提供用于捕获、处理和回放取样的音频数据的接口和类。 javax.sound.sampled.spi 在提供新音频设备、声音文件 reader 和 writer,或音频格式转换器时,提供将为其创建子类的服务提供者的抽象类。 javax.sql 为通过 JavaTM 编程语言进行服务器端数据源访问和处理提供 API。 javax.sql.rowset JDBC RowSet 实现的标准接口和基类。 javax.sql.rowset.serial 提供实用工具类,允许 SQL 类型与 Java 编程语言数据类型之间的可序列化映射关系。 javax.sql.rowset.spi 第三方供应商在其同步提供者的实现中必须使用的标准类和接口。 javax.swing 提供一组“轻级”(全部是 Java 语言)组件,尽让这些组件在所有平台上的工作方式都相同。 javax.swing.border 提供围绕 Swing 组件绘制特殊边框的类和接口。 javax.swing.colorchooser 包含供 JColorChooser 组件使用的类和接口。 javax.swing.event 供 Swing 组件触发的事件使用。 javax.swing.filechooser 包含 JFileChooser 组件使用的类和接口。 javax.swing.plaf 提供一个接口和许多抽象类,Swing 用它们来提供自己的可插入外观功能。 javax.swing.plaf.basic 提供了根据基本外观构建的用户界面对象。 javax.swing.plaf.metal 提供根据 Java 外观(曾经代称为 Metal)构建的用户界面对象,Java 外观是默认外观。 javax.swing.plaf.multi 提供了组合两个或多个外观的用户界面对象。 javax.swing.plaf.synth Synth 是一个可更换皮肤 (skinnable) 的外观,在其中可委托所有绘制。 javax.swing.table 提供用于处理 javax.swing.JTable 的类和接口。 javax.swing.text 提供类 HTMLEditorKit 和创建 HTML 文本编辑器的支持类。 javax.swing.text.html 提供类 HTMLEditorKit 和创建 HTML 文本编辑器的支持类。 javax.swing.text.html.parser 提供默认的 HTML 解析器以及支持类。 javax.swing.text.rtf 提供一个类 (RTFEditorKit),用于创建富文本格式(Rich-Text-Format)的文本编辑器。 javax.swing.tree 提供处理 javax.swing.JTree 的类和接口。 javax.swing.undo 允许开发人员为应用程序(例如文本编辑器)中的撤消/恢复提供支持。 javax.transaction 包含解组期间通过 ORB 机制抛出的三个异常。 javax.transaction.xa 提供定义事务管理器和资源管理器之间的协定的 API,它允许事务管理器添加或删除 JTA 事务中的资源对象(由资源管理器驱动程序提供)。 javax.xml 根据 XML 规范定义核心 XML 常和功能。 javax.xml.bind 为包含解组、编组和验证功能的客户端应用程序提供运行时绑定框架。 javax.xml.bind.annotation 定义将 Java 程序元素定制成 XML 模式映射的注释。 javax.xml.bind.annotation.adapters XmlAdapter 及其规范定义的子类允许任意 Java 类与 JAXB 一起使用。 javax.xml.bind.attachment 此包由基于 MIME 的包处理器实现,该处理器能够解释并创建基于 MIME 的包格式的已优化的二进制数据。 javax.xml.bind.helpers 仅由 JAXB 提供者用于: 提供某些 javax.xml.bind 接口的部分默认实现。 javax.xml.bind.util 有用的客户端实用工具类。 javax.xml.crypto 用于 XML 加密的通用类。 javax.xml.crypto.dom javax.xml.crypto 包的特定于 DOM 的类。 javax.xml.crypto.dsig 用于生成和验证 XML 数字签名的类。 javax.xml.crypto.dsig.dom javax.xml.crypto.dsig 包特定于 DOM 的类。 javax.xml.crypto.dsig.keyinfo 用来解析和处理 KeyInfo 元素和结构的类。 javax.xml.crypto.dsig.spec XML 数字签名的参数类。 javax.xml.datatype XML/Java 类型映射关系。 javax.xml.namespace XML 名称空间处理。 javax.xml.parsers 提供允许处理 XML 文档的类。 javax.xml.soap 提供用于创建和构建 SOAP 消息的 API。 javax.xml.stream javax.xml.stream.events javax.xml.stream.util javax.xml.transform 此包定义了用于处理转换指令,以及执行从源到结果的转换的一般 API。 javax.xml.transform.dom 此包实现特定于 DOM 的转换 API。 javax.xml.transform.sax 此包实现特定于 SAX2 的转换 API。 javax.xml.transform.stax 提供特定于 StAX 的转换 API。 javax.xml.transform.stream 此包实现特定于流和 URI 的转换 API。 javax.xml.validation 此包提供了用于 XML 文档验证的 API。 javax.xml.ws 此包包含核心 JAX-WS API。 javax.xml.ws.handler 该包定义用于消息处理程序的 API。 javax.xml.ws.handler.soap 该包定义用于 SOAP 消息处理程序的 API。 javax.xml.ws.http 该包定义特定于 HTTP 绑定的 API。 javax.xml.ws.soap 该包定义特定于 SOAP 绑定的 API。 javax.xml.ws.spi 该包定义用于 JAX-WS 2.0 的 SPI。 javax.xml.xpath 此包提供了用于 XPath 表达式的计算和访问计算环境的 object-model neutral API。 org.ietf.jgss 此包提供一个框架,该框架允许应用程序开发人员通过利用统一的 API 使用一些来自各种基础安全机制(如 Kerberos)的安全服务,如验证、数据完整性和和数据机密性。 org.omg.CORBA 提供 OMG CORBA API 到 JavaTM 编程语言的映射,包括 ORB 类,如果已实现该类,则程序员可以使用此类作为全功能对象请求代理(Object Request Broker,ORB)。 org.omg.CORBA_2_3 CORBA_2_3 包定义对 Java[tm] Standard Edition 6 中现有 CORBA 接口所进行的添加。 org.omg.CORBA_2_3.portable 提供输入和输出值类型的各种方法,并包含 org/omg/CORBA/portable 包的其他更新。 org.omg.CORBA.DynAnyPackage 提供与 DynAny 接口一起使用的异常(InvalidValue、Invalid、InvalidSeq 和 TypeMismatch)。 org.omg.CORBA.ORBPackage 提供由 ORB.resolve_initial_references 方法抛出的异常 InvalidName,以及由 ORB 类中的动态 Any 创建方法抛出的异常 InconsistentTypeCode。 org.omg.CORBA.portable 提供可移植性层,即可以使一个供应商生成的代码运行在另一个供应商 ORB 上的 ORB API 集合。 org.omg.CORBA.TypeCodePackage 提供用户定义的异常 BadKind 和 Bounds,它们将由 TypeCode 类中的方法抛出。 org.omg.CosNaming 为 Java IDL 提供命名服务。 org.omg.CosNaming.NamingContextExtPackage 此包包含以下在 org.omg.CosNaming.NamingContextExt 中使用的类: AddressHelper StringNameHelper URLStringHelper InvalidAddress 包规范 有关 Java[tm] Platform, Standard Edition 6 ORB 遵守的官方规范的受支持部分的明确列表,请参阅 Official Specifications for CORBA support in Java[tm] SE 6。 org.omg.CosNaming.NamingContextPackage 此包包含 org.omg.CosNaming 包的 Exception 类。 org.omg.Dynamic 此包包含 OMG Portable Interceptor 规范 http://cgi.omg.org/cgi-bin/doc?ptc/2000-08-06 的第 21.9 小节中指定的 Dynamic 模块。 org.omg.DynamicAny 提供一些类和接口使得在运行时能够遍历与 any 有关联的数据值,并提取数据值的基本成分。 org.omg.DynamicAny.DynAnyFactoryPackage 此包包含 DynamicAny 模块的 DynAnyFactory 接口中的类和异常,该模块在 OMG The Common Object Request Broker: Architecture and Specification http://cgi.omg.org/cgi-bin/doc?formal/99-10-07 的第 9.2.2 小节中指定。 org.omg.DynamicAny.DynAnyPackage 此包包含 DynAny 模块的 DynAnyFactory 接口中的类和异常,该模块在 OMG The Common Object Request Broker: Architecture and Specification http://cgi.omg.org/cgi-bin/doc?formal/99-10-07 的第 9.2 小节中指定。 org.omg.IOP 此包包含在 OMG 文档 The Common Object Request Broker: Architecture and Specification http://cgi.omg.org/cgi-bin/doc?formal/99-10-07 的 13.6.小节中指定的 IOP 模块。 org.omg.IOP.CodecFactoryPackage 此包包含 IOP::CodeFactory 接口中指定的异常(作为 Portable Interceptor 规范的一部分)。 org.omg.IOP.CodecPackage 此包根据 IOP::Codec IDL 接口定义生成。 org.omg.Messaging 此包包含 OMG Messaging Interceptor 规范 http://cgi.omg.org/cgi-bin/doc?formal/99-10-07 中指定的 Messaging 模块。 org.omg.PortableInterceptor 提供一个注册 ORB 钩子 (hook) 的机制,通过这些钩子 ORB 服务可以截取执行 ORB 的正常流。 org.omg.PortableInterceptor.ORBInitInfoPackage 此包包含 OMG Portable Interceptor 规范 http://cgi.omg.org/cgi-bin/doc?ptc/2000-08-06 的第 21.7.2 小节中指定的 PortableInterceptor 模块的 ORBInitInfo 本地接口中的异常和 typedef。 org.omg.PortableServer 提供一些类和接口,用来生成跨多个供应商 ORB 的可移植应用程序的服务器端。 org.omg.PortableServer.CurrentPackage 提供各种方法实现,这些实现能够访问调用方法的对象的身份。 org.omg.PortableServer.POAManagerPackage 封装 POA 关联的处理状态。 org.omg.PortableServer.POAPackage 允许程序员构造可在不同 ORB 产品间移植的对象实现。 org.omg.PortableServer.portable 提供一些类和接口,用来生成跨多个供应商 ORB 的可移植应用程序的服务器端。 org.omg.PortableServer.ServantLocatorPackage 提供定位 servant 的类和接口。 org.omg.SendingContext 为值类型的编组提供支持。 org.omg.stub.java.rmi 包含用于 java.rmi 包中出现的 Remote 类型的 RMI-IIOP Stub。 org.w3c.dom 为文档对象模型 (DOM) 提供接口,该模型是 Java API for XML Processing 的组件 API。 org.w3c.dom.bootstrap org.w3c.dom.events org.w3c.dom.ls org.xml.sax 此包提供了核心 SAX API。 org.xml.sax.ext 此包包含适合的 SAX 驱动程序不一定支持的 SAX2 设施的接口。 org.xml.sax.helpers 此包包含“帮助器”类,其中包括对引导基于 SAX 的应用程序的支持。

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧