@sequence_name varchar(200), @sequence_value INT output
AS BEGIN -- DECLARE @sequence_value INT; SET NOCOUNT ON set @sequence_value = -1;
begin TRANSACTION update my_seq SET sequence_value=sequence_value+1 WHERE sequence_name=@sequence_name ; select @sequence_value=sequence_value from my_seq WHERE sequence_name=@sequence_name ; COMMIT TRANSACTION
SET NOCOUNT OFF
RETURN @sequence_value END GO
存储过程做的事主要是:把键值加1后,马上更新数据库里的数据,最后返回处理后的下一数值.
应用系统运行一段时间会出现如下异常: org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call dbo.GET_NEXTVAL(?, ?)}]; SQL state [40001]; error code [1205]; [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]事务(进程 ID 58)与另一个进程已被死锁在 lock 资源上,且该事务已被选作死锁牺牲品。请重新运行该事务。; nested exception is java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]事务(进程 ID 58)与另一个进程已被死锁在 lock 资源上,且该事务已被选作死锁牺牲品。请重新运行该事务。 java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]事务(进程 ID 58)与另一个进程已被死锁在 lock 资源上,且该事务已被选作死锁牺牲品。请重新运行该事务。
CREATE PROCEDURE GET_NEXTVAL
@sequence_name varchar(200),
@sequence_value INT output
AS
BEGIN
-- DECLARE @sequence_value INT;
SET NOCOUNT ON
set @sequence_value = -1;
wait delay '00:00:00.1'
begin TRANSACTION
update my_seq(rowlock)
SET sequence_value=sequence_value+1
WHERE sequence_name=@sequence_name ;
select @sequence_value=sequence_value from my_seq(nolock)
WHERE sequence_name=@sequence_name ;
COMMIT TRANSACTION
SET NOCOUNT OFF
RETURN @sequence_value
END
GO
------解决方案--------------------
------解决方案-------------------- 这是一个并发性的问题,不应该仅仅从解决死锁这个角度考虑,否则即便暂时解决了死锁,可能也会出现其他的比如数据错误 我认为如果是应该再调用这个过程的代码加控制,每一个时刻保证对一个表(sequence_name ),只能有一个进程访问,不通表才能同时访问 或者对每个事务设置优先级,不过性能可能不如前者了
------解决方案-------------------- 这么简单的过程也能死锁?不用强制什么锁吧
------解决方案-------------------- 可以提高一下效率 update my_seq SET @sequence_value = sequence_value+1,sequence_value=sequence_value+1 WHERE sequence_name=@sequence_name ;