高并发情况下的数据库异常,请大虾们指教

TH凯歌 2011-01-10 10:42:05
有三张表,
T1是存储详细数据的
T1
(
SN Int, --(PK)
PNo NVarChar(40), --(PK)
PName NVarChar(100)
...
)

T2是存储串号的
T2
(
SN Int, --(PK)
SNName NVarChar(100)
...
)

T3是存储一个队列的
T3
(
UserID Int, --(PK)
SN Int, --(PK)
PNo NVarChar(40), --(PK)
SName NVarChar(100),
PName NVarChar(100)
...
)

每次从T2中获取一个SN,然后再抓取对应T1表中的数据,插入到T3表中

要求是T2中的任一SN只能被获取一次,数据并发量较大,可能200人左右同时在线操作(每3秒左右一次)
...全文
140 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
TH凯歌 2011-01-12
  • 打赏
  • 举报
回复
BEGIN TRY
BEGIN TRAN
SELECT Top 1 @SN = SN FROM T2

INSERT INTO T3
SELECT @UserID AS UserID, A.SN, B.PNo, A.SName, B.PName
FROM T2 A WITH(READPAST), T1 B WITH(READPAST)
WHERE A.SN = B.SN
AND A.SN = @SN

IF @@RowCount > 0
BEGIN
DELETE T2 WHERE SN = @SN
END
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
END CATCH

现在这样子基本能解决,SELECT TOP时可能需要全表扫描,所以必须要指定跳过锁定行,不然SELECT语句会造成死锁
TH凯歌 2011-01-12
  • 打赏
  • 举报
回复
coleling:
但这样子可能会造成T1插入T3时会有重复
dawugui 2011-01-10
  • 打赏
  • 举报
回复
1 如何锁一个表的某一行

A 连接中执行

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

begin tran

select * from tablename with (rowlock) where id=3

waitfor delay '00:00:05'

commit tran

B连接中如果执行

update tablename set colname='10' where id=3 --则要等待5秒

update tablename set colname='10' where id<>3 --可立即执行

2 锁定数据库的一个表

SELECT * FROM table WITH (HOLDLOCK)


注意: 锁定数据库的一个表的区别

SELECT * FROM table WITH (HOLDLOCK)
其他事务可以读取表,但不能更新删除

SELECT * FROM table WITH (TABLOCKX)
其他事务不能读取表,更新和删除
TH凯歌 2011-01-10
  • 打赏
  • 举报
回复
BEGIN TRY
BEGIN TRAN
SELECT Top 1 @SN = SN FROM T2 WITH(ROWLOCK, XLOCK, READPAST)

INSERT INTO T3
SELECT @UserID AS UserID, A.SN, B.PNo, A.SName, B.PName
FROM T2 A, T1 B
WHERE A.SN = B.SN
AND A.SN = @SN

IF @@RowCount > 0
BEGIN
DELETE T2 WHERE SN = @SN
END
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
END CATCH


这个语句该怎么改呢?
使用后,如果并发量 > 20后,可能会出现重复数据的问题
coleling 2011-01-10
  • 打赏
  • 举报
回复
楼主,为了追求高并发,可以这样改(不加任何锁和事务)

DECLARE @SN Int, @SName NVarChar(100)

SELECT Top 1 @SN = SN, @SName = SName FROM T2
DELETE FROM T2 WHERE SN = @SN

WHILE @@RowCount = 0
BEGIN
SELECT Top 1 @SN = SN, @SName = SName FROM T2
DELETE FROM T2 WHERE SN = @SN
END

INSERT INTO T3
SELECT @UserID AS UserID, @SN, PNo, @SName, PName
FROM T1
WHERE SN = @SN


楼主,记得结贴哦
長胸為富 2011-01-10
  • 打赏
  • 举报
回复

--获取和删除SN地方,建议修改如下:

DECLARE @SNs table(SN int)
DECLARE @SN int
DELETE TOP (1) FROM T2 WITH (READPAST) OUTPUT DELETED.SN INTO @SNs
SELECT @SN = SN FROM @SNs


TH凯歌 2011-01-10
  • 打赏
  • 举报
回复
如果加表锁,则对高并发有很大影响
目前我的方法就是锁定那一行,然后再删除掉,理论上来说应该不会有重复的,但……………………

22,209

社区成员

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

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