关于一个并发查询时问题 百分相送

thooy 2009-12-24 04:49:07
我有一个应用,一个表叫c_pool(id,clientid)吧,用来存放的是客户名单,另一个表叫c_call(id,clientid,seatnumber) .我们有二十个客服会同时从c_pool里随机取1条客户数据出来,添加到c_call中并对应自己的客服号,同时将这条客户数据从c_pool中删除。

遇到的问题就是可能两个客服会同时取到同一个客户数据,这是不允许的。所以我觉得应该用锁来搞定,但本人对这一块用得很少,请帮我提一个详细的解决方案出来,100分全送。

可能的问题有:
1、同一客户数据不能被同一客服选中。
2、不能对c_pool进行TABLOCK,因为客服主管要随时查看c_pool里还余多少条数据。
3、如果使用锁的话,怎么防止死锁。

...全文
145 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
thooy 2009-12-24
  • 打赏
  • 举报
回复
非常感谢,因为我首先想到的就是用sqlserver的锁,然后直接写一个事务同时处理掉这个查询,插入和删除的操作,不知道您对于这方面有没有好的提议!
dawugui 2009-12-24
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 thooy 的回复:]
OK,这下明白你的想法了,思路很棒!
如果直接用
update c_pool set customer='客服1' where  id in(select top n id from c_pool where customer = '' or customer is null order by newid() ) 这样一条语句能不能解决这个占用的问题?因为在update一条数据时,这时应该有一个排他访问的。这样写会不会有什么问题?

按照你的思路来,可能程序上处理得就得多一点,因为我不可能一直把这些作了标志的数据留在这个表里,这个表里的数据量会相当大,所以我必须要转到别的表里,也就是我一开始所说的那个c_call的表里。

如果直接用数据库的事务处理直接操作,有没有更好的办法处理这个取出,插入,删除的工作?
[/Quote]
同样会.

所以,你得在update之后判断是否成功.
不成功,就再次去随机,或...,直到成功或数据已处理完毕.

这其实就是个占位法,谁占住了谁先用.
不过得按照我一楼说的,加个时间字段,以免某人占着厕所不拉屎,遇到这样的人只能手动或自动去清理他.
thooy 2009-12-24
  • 打赏
  • 举报
回复
OK,这下明白你的想法了,思路很棒!
如果直接用
update c_pool set customer='客服1' where id in(select top n id from c_pool where customer = '' or customer is null order by newid() ) 这样一条语句能不能解决这个占用的问题?因为在update一条数据时,这时应该有一个排他访问的。这样写会不会有什么问题?

按照你的思路来,可能程序上处理得就得多一点,因为我不可能一直把这些作了标志的数据留在这个表里,这个表里的数据量会相当大,所以我必须要转到别的表里,也就是我一开始所说的那个c_call的表里。

如果直接用数据库的事务处理直接操作,有没有更好的办法处理这个取出,插入,删除的工作?
dawugui 2009-12-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 thooy 的回复:]
我想问的是执行了
select top 1 * from c_pool where customer = '' or customer is null order by newid()
比如我取到了clientid=100的这个客户,别人在同时就肯定取不到clientid=100的这个客户吗?然后
update c_pool set customer='客服1' where clientid=100
但是我不能保证在我执行update前,别人是不是也选中了这条数据
[/Quote]

update c_pool set customer='客服1' where clientid=100 and (customer = '' or customer is null)

你需要在程序中判断,保存是否成功.
如果保存不成功,代表有人占用了.
这下应该明白了?

如果保存不成功,则让这个用户再次去随机....
thooy 2009-12-24
  • 打赏
  • 举报
回复
爱新觉罗.毓华,你有QQ或是别的交流方式吗?我直接跟你交流一下,然后送分。
thooy 2009-12-24
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 dawugui 的回复:]
是同样的一个道理.

随机选,判断到customer存在数据,则再次随机,直到customer为空为止.

多条也是这样一来,某个用户选择了几个,就把这几个占用了,别的用户不能使用这几个.

我想我已经说得很明白了.

大致语句可以如下:

select top 1 * from tb where customer = '' or customer is null order by newid()

select top n * from tb where customer = '' or customer is null order by newid()

[/Quote]

我想问的是执行了
select top 1 * from c_pool where customer = '' or customer is null order by newid()
比如我取到了clientid=100的这个客户,别人在同时就肯定取不到clientid=100的这个客户吗?然后
update c_pool set customer='客服1' where clientid=100
但是我不能保证在我执行update前,别人是不是也选中了这条数据
dawugui 2009-12-24
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 thooy 的回复:]
我明白你的意思,你是指当一个客服选中一条数据后,加一个标志(update一下)别人就不会去选他了,但是我的前提是在数据库里随机取一条出来,那可能会出现两个客服同时选中了同一个客户。
[/Quote]
[Quote=引用 7 楼 thooy 的回复:]
还有一个问题就是,如果要每个客服去c_pool表里取多条记录呢?
[/Quote]

是同样的一个道理.

随机选,判断到customer存在数据,则再次随机,直到customer为空为止.

多条也是这样一来,某个用户选择了几个,就把这几个占用了,别的用户不能使用这几个.

我想我已经说得很明白了.

大致语句可以如下:

select top 1 * from tb where customer = '' or customer is null order by newid()

select top n * from tb where customer = '' or customer is null order by newid()


thooy 2009-12-24
  • 打赏
  • 举报
回复
还有一个问题就是,如果要每个客服去c_pool表里取多条记录呢?
thooy 2009-12-24
  • 打赏
  • 举报
回复
我明白你的意思,你是指当一个客服选中一条数据后,加一个标志(update一下)别人就不会去选他了,但是我的前提是在数据库里随机取一条出来,那可能会出现两个客服同时选中了同一个客户。
nalnait 2009-12-24
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 dawugui 的回复:]
对这个表
c_pool(id,clientid)

加个字段,列名:customer,存放取数据的那个客户,

如果customer字段存在数据,则后面的客户不能取这条数据,转而去取其他的数据。

例如数据假设如下:

c_pool
id , clientid , customer
1    1          客户1
2    2          客户2
3    3
4    4
5    5

那么这个时候id = 1 和2这两条不允许其他用户去获取。

如果再要考虑周全点,再加个时间字段,存放客户取数据的时间,如果超过某个时间,还没有处理,则手动或自动将这个数据的customer字段设置为空。

不知道你看明白我的意思没有?
[/Quote]
这个建议可行
mxc1225 2009-12-24
  • 打赏
  • 举报
回复
学习了!!
--小F-- 2009-12-24
  • 打赏
  • 举报
回复
第2个问题感觉使用数据库的权限可以满足要求
--小F-- 2009-12-24
  • 打赏
  • 举报
回复
如何避免死锁
1 使用事务时,尽量缩短事务的逻辑处理过程,及早提交或回滚事务;
2 设置死锁超时参数为合理范围,如:3分钟-10分种;超过时间,自动放弃本次操作,避免进程悬挂;
3 优化程序,检查并避免死锁现象出现;
4 .对所有的脚本和SP都要仔细测试,在正是版本之前。
5 所有的SP都要有错误处理(通过@error)
6 一般不要修改SQL SERVER事务的默认级别。不推荐强行加锁

dawugui 2009-12-24
  • 打赏
  • 举报
回复
对这个表
c_pool(id,clientid)

加个字段,列名:customer,存放取数据的那个客户,

如果customer字段存在数据,则后面的客户不能取这条数据,转而去取其他的数据。

例如数据假设如下:

c_pool
id , clientid , customer
1 1 客户1
2 2 客户2
3 3
4 4
5 5

那么这个时候id = 1 和2这两条不允许其他用户去获取。

如果再要考虑周全点,再加个时间字段,存放客户取数据的时间,如果超过某个时间,还没有处理,则手动或自动将这个数据的customer字段设置为空。

不知道你看明白我的意思没有?

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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