Spring 事务 - 在 Sybase 过程中创建临时 table 时出现 Propagation.REQUIRED 问题
Spring transaction - Propagation.REQUIRED issue when creating temporary table in Sybase procedure
我已经在我的项目中的 DAO 方法上应用了 spring 事务,如下所示
@Transactional(readOnly=false, propagation=Propagation.REQUIRED)
public String updateUser(Integer userId, String address)
{
//calling sybase procedure to update user address
}
Sybase 程序
CREATE PROCEDURE sp_update_user_address
@user_id numeric(9,0),
@address varchar(500)
AS
BEGIN
UPDATE users
SET address = @address,
WHERE user_id = @user_id
and user_status <> 'I'
END
go
EXEC sp_procxmode 'sp_update_user_address', 'chained'
程序执行精细更新用户table中的记录。但是失败(记录未更新)当我们在过程中创建临时table时,如下所示
//creating temporary table in procedure for some logic
CREATE TABLE #usertemp
(
id int null,
address varchar(500)
)
1) 为什么在过程中创建临时 table 会导致事务(更新操作)失败?
我通过使用 [=35 注释方法解决了这个问题=].
2)为什么Propagation.REQUIRED没有执行程序(有临时table)成功?
3) 在过程中创建临时 table 是否启动隐式事务?
如果没有关于你的过程(w/temp table)如何失败的更多细节,我将猜测这个问题......
- 创建过程后执行
sp_procxmode / chained
,这意味着过程预计 运行 链式事务模式(即,将从事务中调用过程)
- proc 运行没有#temp table
- 尝试创建#temp table 时的过程 'fails';我猜 'fails' 意味着你收到一条错误消息......类似于...... "can't create #temp table inside a transaction"
- 我假设这是 Sybase ASE ...
默认情况下,Sybase ASE 不允许事务内的 DDL;这包括不允许在交易中创建#temp table。
看来您的应用程序可能 运行处于链式事务模式;这意味着所有数据库调用始终在事务内,包括尝试创建#temp table 的存储过程执行,即,proc 试图在事务内创建#temp table .
并且由于事务内部不允许 DDL(例如,#temp table 创建),proc 执行失败(并且 ASE 生成错误,基本上说明您无法创建 #temp table 在交易中)。
查看 Spring 的 NOT_SUPPORTED 选项的文档,(在我看来)这会导致 proc 在外部执行任何事务控制(例如,切换到非链接模式);最终结果是,由于 proc 不在事务内,现在可以创建 #temp table。
我还猜测通过切换 to/from NOT_SUPPORTED 你可能会打破一个更大的交易(不能从这个小您的代码的花絮;您必须查看您的整体事务模型,看看这是好事还是坏事。
如果我的 assumptions/guesses 是正确的,您将不得不(重新)访问您的应用程序的事务模型,着眼于确保您没有发布 DDL(例如,创建一个 #temp table) 在交易中。
我已经在我的项目中的 DAO 方法上应用了 spring 事务,如下所示
@Transactional(readOnly=false, propagation=Propagation.REQUIRED)
public String updateUser(Integer userId, String address)
{
//calling sybase procedure to update user address
}
Sybase 程序
CREATE PROCEDURE sp_update_user_address
@user_id numeric(9,0),
@address varchar(500)
AS
BEGIN
UPDATE users
SET address = @address,
WHERE user_id = @user_id
and user_status <> 'I'
END
go
EXEC sp_procxmode 'sp_update_user_address', 'chained'
程序执行精细更新用户table中的记录。但是失败(记录未更新)当我们在过程中创建临时table时,如下所示
//creating temporary table in procedure for some logic
CREATE TABLE #usertemp
(
id int null,
address varchar(500)
)
1) 为什么在过程中创建临时 table 会导致事务(更新操作)失败?
我通过使用 [=35 注释方法解决了这个问题=].
2)为什么Propagation.REQUIRED没有执行程序(有临时table)成功?
3) 在过程中创建临时 table 是否启动隐式事务?
如果没有关于你的过程(w/temp table)如何失败的更多细节,我将猜测这个问题......
- 创建过程后执行
sp_procxmode / chained
,这意味着过程预计 运行 链式事务模式(即,将从事务中调用过程) - proc 运行没有#temp table
- 尝试创建#temp table 时的过程 'fails';我猜 'fails' 意味着你收到一条错误消息......类似于...... "can't create #temp table inside a transaction"
- 我假设这是 Sybase ASE ...
默认情况下,Sybase ASE 不允许事务内的 DDL;这包括不允许在交易中创建#temp table。
看来您的应用程序可能 运行处于链式事务模式;这意味着所有数据库调用始终在事务内,包括尝试创建#temp table 的存储过程执行,即,proc 试图在事务内创建#temp table .
并且由于事务内部不允许 DDL(例如,#temp table 创建),proc 执行失败(并且 ASE 生成错误,基本上说明您无法创建 #temp table 在交易中)。
查看 Spring 的 NOT_SUPPORTED 选项的文档,(在我看来)这会导致 proc 在外部执行任何事务控制(例如,切换到非链接模式);最终结果是,由于 proc 不在事务内,现在可以创建 #temp table。
我还猜测通过切换 to/from NOT_SUPPORTED 你可能会打破一个更大的交易(不能从这个小您的代码的花絮;您必须查看您的整体事务模型,看看这是好事还是坏事。
如果我的 assumptions/guesses 是正确的,您将不得不(重新)访问您的应用程序的事务模型,着眼于确保您没有发布 DDL(例如,创建一个 #temp table) 在交易中。