create table my_seq(
sequence_name varchar(50) not null,
sequence_value int(4)
)
自定义存储过程如下:
SQL code
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;
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 资源上,且该事务已被选作死锁牺牲品。请重新运行该事务。
网络上找到很多类似这样的问题,但我还是没有找到解决的办法.
42 个解决方案
#1
http://blog.csdn.net/arrow_gx/archive/2009/03/19/4004938.aspx
http://blog.csdn.net/arrow_gx/archive/2008/06/01/2501368.aspx
锁的概念级例程分析,也许对楼主有点用处
另外,修改一下存储过程,
强制 update 使用行级锁ROWLOCK,缩小锁的粒度,
select 使用 nolock ,试试这样能否解决你的问题
http://blog.csdn.net/arrow_gx/archive/2008/06/01/2501368.aspx
锁的概念级例程分析,也许对楼主有点用处
另外,修改一下存储过程,
强制 update 使用行级锁ROWLOCK,缩小锁的粒度,
select 使用 nolock ,试试这样能否解决你的问题
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;
begin TRANSACTION
update my_seq with(ROWLOCK)
SET sequence_value=sequence_value+1
WHERE sequence_name=@sequence_name ;
select @sequence_value=sequence_value
from my_seq with(nolock)
WHERE sequence_name=@sequence_name ;
COMMIT TRANSACTION
SET NOCOUNT OFF
RETURN @sequence_value
END
GO
#2
感觉是事务和事务冲突导致的锁,这样你在这里加上一句;
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
#3
关注
#4
学习一下
#5
先试下arrow_gx的方法,不过"select 使用 nolock"我担心会读脏数据.
#6
ORACLE没有用过,继续关注
#7
如果存储过程就如楼主写的这个简单的话,建议把事务去掉试试。
#8
加这句就好了
select @sequence_value=sequence_value from my_seq(nolock)
WHERE sequence_name=@sequence_name ;
#9
存储过程不用动。
TRY:
TRY:
CREATE CLUSTERED INDEX PK_IDX ON my_seq(sequence_name)
GO
#10
ding
#11
呵呵,担心这个的话, select 也指定使用 ROWLOCK 行级锁好了
另外,在 sequence_name 字段建立索引,如果这个字段是唯一的话,直接设置成主键,对查询性能可以提高很多的
#12
顶起
#13
学习了
#14
up
#15
死锁是4种情况都满足,你打破其中一个就不死锁了
#16
mark
#17
学习
#18
学习 学习
#19
很不错 顶你一个
#20
Mark!
#21
MARK~~
#22
回帖是一种美德!每天回帖即可获得 10 分可用分
#23
学习一下啊
#24
这是一个并发性的问题,不应该仅仅从解决死锁这个角度考虑,否则即便暂时解决了死锁,可能也会出现其他的比如数据错误
我认为如果是应该再调用这个过程的代码加控制,每一个时刻保证对一个表(sequence_name ),只能有一个进程访问,不通表才能同时访问
或者对每个事务设置优先级,不过性能可能不如前者了
我认为如果是应该再调用这个过程的代码加控制,每一个时刻保证对一个表(sequence_name ),只能有一个进程访问,不通表才能同时访问
或者对每个事务设置优先级,不过性能可能不如前者了
#25
主要是学习
#26
主要是蹭分
#27
先试下arrow_gx的方法,不过"select 使用 nolock"我担心会读脏数据.
#28
不为得分。
#29
xue xi ing
#30
guan zhu yi xia ..
#31
up
#32
答题的还没1/3呢.20多个都是顶的....嗨....
#33
#34
我给方法加同步(synchronized)了也没用,还是报同样的异常.
#35
这么简单的过程也能死锁?不用强制什么锁吧
#36
可以提高一下效率
update my_seq
SET @sequence_value = sequence_value+1,sequence_value=sequence_value+1
WHERE sequence_name=@sequence_name ;
产生锁的话,显然是你运行此存储过程太频繁了,有些程序不是你想不要多改就能不改的
当然的设计显然是自己在制造瓶颈!
update my_seq
SET @sequence_value = sequence_value+1,sequence_value=sequence_value+1
WHERE sequence_name=@sequence_name ;
产生锁的话,显然是你运行此存储过程太频繁了,有些程序不是你想不要多改就能不改的
当然的设计显然是自己在制造瓶颈!
#37
Mark
#38
发现一个很低级的问题,我用工具把数据库从Oracle迁移到MsSQL的,重新检查了下发现MsSQL上的主键唯一约束有的没有生成.加上后,再没有发现那个异常了.
#39
Up 学习!!
#40
#41
学习了
#42
学习了,用加索引的方法解决了问题, 非常感谢 Garnett_KG
#1
http://blog.csdn.net/arrow_gx/archive/2009/03/19/4004938.aspx
http://blog.csdn.net/arrow_gx/archive/2008/06/01/2501368.aspx
锁的概念级例程分析,也许对楼主有点用处
另外,修改一下存储过程,
强制 update 使用行级锁ROWLOCK,缩小锁的粒度,
select 使用 nolock ,试试这样能否解决你的问题
http://blog.csdn.net/arrow_gx/archive/2008/06/01/2501368.aspx
锁的概念级例程分析,也许对楼主有点用处
另外,修改一下存储过程,
强制 update 使用行级锁ROWLOCK,缩小锁的粒度,
select 使用 nolock ,试试这样能否解决你的问题
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;
begin TRANSACTION
update my_seq with(ROWLOCK)
SET sequence_value=sequence_value+1
WHERE sequence_name=@sequence_name ;
select @sequence_value=sequence_value
from my_seq with(nolock)
WHERE sequence_name=@sequence_name ;
COMMIT TRANSACTION
SET NOCOUNT OFF
RETURN @sequence_value
END
GO
#2
感觉是事务和事务冲突导致的锁,这样你在这里加上一句;
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
#3
关注
#4
学习一下
#5
先试下arrow_gx的方法,不过"select 使用 nolock"我担心会读脏数据.
#6
ORACLE没有用过,继续关注
#7
如果存储过程就如楼主写的这个简单的话,建议把事务去掉试试。
#8
加这句就好了
select @sequence_value=sequence_value from my_seq(nolock)
WHERE sequence_name=@sequence_name ;
#9
存储过程不用动。
TRY:
TRY:
CREATE CLUSTERED INDEX PK_IDX ON my_seq(sequence_name)
GO
#10
ding
#11
呵呵,担心这个的话, select 也指定使用 ROWLOCK 行级锁好了
另外,在 sequence_name 字段建立索引,如果这个字段是唯一的话,直接设置成主键,对查询性能可以提高很多的
#12
顶起
#13
学习了
#14
up
#15
死锁是4种情况都满足,你打破其中一个就不死锁了
#16
mark
#17
学习
#18
学习 学习
#19
很不错 顶你一个
#20
Mark!
#21
MARK~~
#22
回帖是一种美德!每天回帖即可获得 10 分可用分
#23
学习一下啊
#24
这是一个并发性的问题,不应该仅仅从解决死锁这个角度考虑,否则即便暂时解决了死锁,可能也会出现其他的比如数据错误
我认为如果是应该再调用这个过程的代码加控制,每一个时刻保证对一个表(sequence_name ),只能有一个进程访问,不通表才能同时访问
或者对每个事务设置优先级,不过性能可能不如前者了
我认为如果是应该再调用这个过程的代码加控制,每一个时刻保证对一个表(sequence_name ),只能有一个进程访问,不通表才能同时访问
或者对每个事务设置优先级,不过性能可能不如前者了
#25
主要是学习
#26
主要是蹭分
#27
先试下arrow_gx的方法,不过"select 使用 nolock"我担心会读脏数据.
#28
不为得分。
#29
xue xi ing
#30
guan zhu yi xia ..
#31
up
#32
答题的还没1/3呢.20多个都是顶的....嗨....
#33
#34
我给方法加同步(synchronized)了也没用,还是报同样的异常.
#35
这么简单的过程也能死锁?不用强制什么锁吧
#36
可以提高一下效率
update my_seq
SET @sequence_value = sequence_value+1,sequence_value=sequence_value+1
WHERE sequence_name=@sequence_name ;
产生锁的话,显然是你运行此存储过程太频繁了,有些程序不是你想不要多改就能不改的
当然的设计显然是自己在制造瓶颈!
update my_seq
SET @sequence_value = sequence_value+1,sequence_value=sequence_value+1
WHERE sequence_name=@sequence_name ;
产生锁的话,显然是你运行此存储过程太频繁了,有些程序不是你想不要多改就能不改的
当然的设计显然是自己在制造瓶颈!
#37
Mark
#38
发现一个很低级的问题,我用工具把数据库从Oracle迁移到MsSQL的,重新检查了下发现MsSQL上的主键唯一约束有的没有生成.加上后,再没有发现那个异常了.
#39
Up 学习!!
#40
#41
学习了
#42
学习了,用加索引的方法解决了问题, 非常感谢 Garnett_KG