请教一个多线程访问数据库的问题

king200920092009 2017-08-07 01:30:22
任务描述:在sql server中有两张表,表1为原始数据,表2为分析数据。程序功能是从表1中逐条读取原始数据,进行分析后形成分析数据,插入表2。因为数据量较大(千万级),所以开发一个方法(方法1)处理表1数据、生成表2数据。在主程序中将表1的数据分为4段,调用了四个task,每个task 均调用方法1。
方法1的处理流程是:建立数据库连接,按照传递进来的开始、结束key值,读取表1数据,进行处理并生成表2数据,插入datatable,然后调用sqlbulkcopy插入表2.。
因为四个task对数据进行了分段,能够保证在方法1中读取表1、插入表2时都是处理不同的数据,所以我没有加锁。
碰到的问题:我重复执行了几次,有时候能够正常完成;有时候会在并发调用方法1时锁住;还有两次在插入表2时( PDbulkCopy.WriteToServer(PQDT);)报错数据库超时。
想请教一下:我对该问题的处理方式是否正确?为什么会在插入表2时报错,是否需要加锁?
谢谢
...全文
498 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
秋的红果实 2017-08-07
  • 打赏
  • 举报
回复
多说一句 多线程不一定能提高效率。 能提高效率的情况之一,如: 一个业务需要A,B两个环节,单线程执行的话,A是瓶颈:A计算出结果需要100秒,然后传给B使用,而B处理只需要0.001秒,为了不让B在空等待,需要将资源(内存+CPU等)往A这边移动,此时才使用多线程,让A1,A2,A3……,一起处理A的运算,解决瓶颈问题
秋的红果实 2017-08-07
  • 打赏
  • 举报
回复
这种场合,不要使用多线程,效率反而会降低,系统维护多线程要消耗不少资源 做好索引,优化好sql树,费时间也只好等待了,因为你的数据库千万级 千万级数据库加锁执行,死的更快 你的数据库分成4块,4个task每个一块,即使不分成4块,你的问题,也不用加锁,加了,数据库负担更重,更容易超时 分析结果写入t2,如果只是简单的“添加”操作,没有和已经存在的数据相关联的情况,也不用加锁;比如购物篮,要加的物品已经存在了,只改变数量即可,要不存在,需要新添加,这就是和已经存在的数据有关联了,这种情况才加锁
吉普赛的歌 2017-08-07
  • 打赏
  • 举报
回复
不赞同你的做法。 数据库不是傻瓜, 你会用多线程, 它也会用多线程, 一个大任务给它, 如果你的CPU是多核, 而且配置有并行处理, 它自然就会按多线程去运行, 没有必要去人为写什么多线程。 这种分析型的报表, 建议写存储过程, 用 SQL Server 的作业来定时执行, 会稳定很多, 不会轻易超时。 至于效率, 你可以贴出SQL,及相关表的索引, 还有相关的执行计划, 我们可以帮你优化。
xdashewan 2017-08-07
  • 打赏
  • 举报
回复
引用 2 楼 king200920092009 的回复:
谢谢。那是否可以理解为在多线程(任务)进行数据库操作时,应遵循以下规则: 1、多线程读取同一张表的数据时,不用加锁。 2、多线程写同一张表时,一定要加共享锁,即使不同线程操作的数据不会发生冲突。 谢谢。
1.读取加不加锁,取决于业务如何设计,对于你的这个设计不用加锁,但不是说任何情况都不需要加锁 2.写的时候加锁是为了程序可控,因为就算你程序不锁,数据库自己也有锁,到时间了就会返回超时 另外提醒一句,多线程操作数据,连接也同样要多个,多线程操作同一数据库连接是错误的
king200920092009 2017-08-07
  • 打赏
  • 举报
回复
谢谢。那是否可以理解为在多线程(任务)进行数据库操作时,应遵循以下规则: 1、多线程读取同一张表的数据时,不用加锁。 2、多线程写同一张表时,一定要加共享锁,即使不同线程操作的数据不会发生冲突。 谢谢。
xdashewan 2017-08-07
  • 打赏
  • 举报
回复
你的做法前半段是没有问题的,问题出在后半段上,多连接读数据是可以,但多连接写数据却是会遇到锁表问题的,尤其是当一个大量耗时数据写入时,其他连接超时也不是没可能。所以写入时可以考虑加锁,或者把线程处理完的数据汇总后再插入。

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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