ALTER PROCEDURE [dbo].[UpdateReadTest]
AS
BEGIN
BEGIN TRANSACTION 
declare @num int
select @num = Num from ReadTest rowlock where Id = 1
set @num = @num + 1
update ReadTest set Num = @num where Id = 1
--update ReadTest set Num = Num + 1 where Id = 1
COMMIT 
END今天在做多线程并发测试的时候,发现在事务里给查询数据加 rowlock 无效,谁能解答一下?
在4x1000以下看不出错误,但并发线程达到5以后开始出现数据错误。

解决方案 »

  1.   

    select @num = Num from ReadTest with(rowlock,xlock) where Id = 1
      

  2.   

    --try
    from ReadTest with(holdlock,tablockx)
      

  3.   

    或者设置事务的隔离级别为
    seriallzable
      

  4.   


    select @num = Num from ReadTest with(rowlock) where Id = 1
      

  5.   


            static void changeNumTran(object id)
            {
                thradNum++;
                for (int i = 0; i < 10000; i++)
                {
                    int num;
                    SqlParameter param = new SqlParameter("@id", id);
                    DbHelperSQL.RunProcedure("UpdateReadTest2", new[] { param }, out num);
                }
                thradNum--;
            }            //  将原始数据清零
                DbHelperSQL.ExecuteSql("update ReadTest set Num = 0");
                DateTime begin = DateTime.Now;
                for (int j = 1; j <= 20; j++ )
                    for (int i = 0; i < 5; i++)
                    {
                        var thread = new Thread(ChangeNum);
                        //var thread = new Thread(changeNumTran);
                        thread.Start(j);
                    }            Thread.Sleep(100);
                while (thradNum > 1)
                    Thread.Sleep(100);我用c#做的开发,按照上面的做法,加xlock后的确能保证数据的准确性。
    不过实测发现,好像这个时候不是行级锁,而变成表锁了。
    上面的代码
    for (int j = 1; j <= 20; j++ )
    标示同时对20行做并发修改,如果是行级锁,没增加一个行并发,会将提高数据库的每秒的执行数,但从实际测试来看,并发操作5行数据和并发操作20行数据每秒执行的sql数是固定的。这个是修改后的存储过程ALTER PROCEDURE [dbo].[UpdateReadTest2]
    @id int
    AS
    BEGIN
    BEGIN TRANSACTION 
    declare @num int
    select @num = Num from ReadTest   where Id = @id
    set @num = @num + 1
    update ReadTest set Num = @num where Id = @id
    waitfor DELAY '000:00:00.01' -- 延时,不让并发时不让数据库的io和cpu成为瓶颈
    --update ReadTest set Num = Num + 1 where Id = 1
    COMMIT 
    END