事务中的表锁定,删除然后在同一事务中插入

4

更新的问题

我进一步调试了这个问题,现在我的代码看起来像这样:

$mssql->beginTransaction();
$mssql->sql("DELETE FROM [TABLE] WHERE [FIELD] = 'Test'");
// Write the result from the above query,
// this will confirm the row was deleted
print_r($mssql->result);

$mssql->sql("SELECT FROM [TABLE] WHERE [FIELD] = 'Test'");
// Write the result from the above query,
// this SHOULD be empty as the row was just deleted
print_r($mssql->result);
$mssql->endTransaction();

上述脚本在一个SQL Server数据库中完美运行,但在另一个数据库(不同服务器上的副本数据库)中却无法正常工作。
第二个数据库能够从表中检索出一行数据,即使该行数据应该已被删除...
附加信息:
1.据我所见,数据库选项中唯一的区别是“启用代理程序”选项,我认为这与此无关。
2.我不知道如何访问或查看事务选项,这些可能与此有关吗?
3.这可能与表锁定有关吗?
SQL跟踪
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P1 nvarchar(6)',N'DELETE FROM TABLE WHERE [FIELD]=@P1',N'M87996'
select @p1
go
declare @p1 int
set @p1=2
exec sp_prepexec @p1 output,NULL,N'SELECT db_name()'
select @p1
go
exec sp_unprepare 2
go
exec sp_unprepare 1
go
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P1 nvarchar(6)',N'SELECT * FROM [TABLE] WHERE [FIELD]=@P1 ',N'M87996'
select @p1
go
exec sp_unprepare 1
go

原问题

这是我第一次使用SQL事务,如果我显得幼稚,请多包涵。

我有一个事务,它从数据库中删除一个项目,然后将更新后的项目插入到相同的主键下。

请考虑以下内容(忽略我的包装类函数):

$mssql->beginTransaction();
$mssql->sql("DELETE FROM [TABLE] WHERE [FIELD] = 'Test'");
$mssql->sql("INSERT INTO [TABLE] ([FIELD]) VALUES ('Test'));
$mssql->endTransaction();

然而,使用以上代码时,我得到了一个“重复主键”错误。这是因为它没有提交第一个查询吗?
因此,在同一事务中同时运行上述两个查询不可能吗?
很遗憾,我不能简单地使用UPDATE命令执行上述操作,因为我必须删除一些行,而无法知道要删除哪些行...
1个回答

3
不,肯定是其他问题。在同一事务中,您无需提交即可始终看到自己的更改,因此当您进行INSERT时,DELETE已经完成。
首先,您需要验证DELETE是否真正删除了行。它可能在匹配WHERE子句时悄悄失败(即未删除任何行,请检查PDO::exec的返回值)。这可能是由于某些排序规则问题与VARCHAR vs. NVARCHAR(Ascii vs. Unicode)相结合引起的。很难猜测。

是的,仍然返回了行 :-( - Ben Carey
你能捕获一个 SQL Profiler 跟踪(默认的 SQL 跟踪模板应该可以)并在这里发布吗? - Remus Rusanu
那我是在服务器上执行,而不是通过查询执行吗? - Ben Carey
你能否发布实际的跟踪文件(.trc文件)?它包含了你发布的信息中缺失的重要信息,例如执行会话。同时请确保捕获开始事务/提交事件。 - Remus Rusanu
2
我已经找出了问题,它与数据库或事务都没有关系。我的 SQL 封装类中有一个 bug,导致每次执行查询时脚本重新连接到数据库。无论如何,非常感谢您的帮助! :-) - Ben Carey
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接