SQL Server UPDATE语句不更新匹配约束的行

时间:2017-08-25 02:12:10

标签: sql-server database sql-update jtds

如果我读到这个问题,我会立即想到"一些白痴在自己做研究之前寻求帮助"。虽然" idiot"是否仍有待观察指定是正确的,我可以向你保证,这不是我的第一次牛仔竞技表演,而且我已经在这面墙上击打了40-80小时。

短篇小说:我的系统执行4次更新语句四次传入四个不同的参数值。根据约束,每次执行应修改大约50,000行。但是,虽然其中两个执行修改了预期的行数,但另外两个只更新了201行。

声明: 为了说服你,我不是一个菜鸟,谁正在更新一个数据库,然后想知道为什么不同数据库中的记录没有更新。

  • 我是一名拥有超过15年经验的程序员,专注于批处理性能至关重要的系统
  • 我对SQL Server的专业水平远低于典型的DBA,但远高于典型的开发人员
  • 正如我上面提到的,我花了40-80个小时来研究这个问题
  • 我没有想法

长篇故事:

有问题的表格如下:

  • MyPkCol - BIGINT - 不参与UPDATE语句。仅限聚集索引中的列
  • MyForeignKeyCol1 - BIGINT - 指向另一个由Update清除的表的指针
  • MyIntCol - INT - 由Update
  • 清除的基本数据
  • MyForeignKeyCol2 - BIGINT - 指向另一个表的指针,该表由Update清除并且是唯一的约束

有一个非聚集索引,只包含MyForeignKeyCol1(不包含)。

还有另一个非聚集索引,只包含MyForeignKeyCol2(不包括)。

MyForeignKeyCol1有一个外键,MyForeignKeyCol2有另一个外键。

更新声明是:

UPDATE T1 
SET MyForeignKeyCol1 = NULL, 
    MyForeignKeyCol2 = NULL, 
    MyIntCol = NULL 
WHERE MyForeignKeyCol2 = ?

问题非常不一致。我已经将该过程运行了200-300次,问题仅发生了3次。

在最近发生的事件中,该表包含大约200,000条记录。 50,000 MyForeignKeyCol2中包含值123,MyForeignKeyCol2中50,000包含值345,MyForeignKeyCol2中50,000包含值567,{{1}中包含值789 }}

该过程执行Update语句4次,传递参数123,345,567和789. 4个更新中的每一个都在单独的事务中执行。数据库驱动程序报告语句修改了以下数量的记录:

  • 50000
  • 201
  • 201
  • 50000

数据库的状态显示49,799条记录保留MyForeignKeyCol2,另有49,799条记录保留MyForeignKeyCol2=345

数据库不包含触发器。

我的第一个理论之一是,在执行UPDATE时,跳过的记录上的MyForeignKeyCol2=567列包含除345或567之外的某些值,然后在UPDATE后面的某些内容用这些值填充列。经过数小时的研究后,99.99%肯定不是这样。

此类行为是否可能是由腐败索引或过时统计信息引起的?

根据我的经验,数据库是我参与的任何系统中最可靠的部分,因此也是我怀疑的最后一件事,但这是我唯一留下的理论。

提前致谢!

1 个答案:

答案 0 :(得分:2)

我仍然没有完整的答案,但我现在已经足够明白,可以将其标记为已回答,以避免其他人浪费时间。有了它,我会提供完整的答案。

注意:我没有提到这是一个Java应用程序。

它似乎是另一个线程(一个服务于某些UI活动的线程),它获取了这个java.sql.Statement对象的句柄,并在第一个和第二个UPDATES之间调用了Statement.setMaxRows(201)。然后可能会再次称它为第三次和第四次更新之间的大量传递。

我总觉得setMaxRows只影响SELECT语句,而该方法的javadoc支持这种误解(IMO)。但是我现在明白它也会影响UPDATE,DELETES和INSERTS(不是100%肯定INSERTS)。将此字段设置为201会导致JTDS驱动程序发送" SET ROWCOUNT 201"在UPDATE语句之前命令SQL Server,这导致SQL Server将UPDATE影响的行数限制为201.

现在剩下的问题是"另一个线程如何处理该连接"?我们使用连接池库,我们还有另一个库,可以帮助进行数据库事务管理。我现在避免命名它们,b / c最可能的罪魁祸首是我们的代码(一如既往)。

感谢所有花费宝贵时间阅读这个长期问题的人。

最终答案!!! 这是JTDS驱动程序的最新版本(1.3.1)中的错误。 https://sourceforge.net/p/jtds/bugs/726/

再次感谢任何花时间审阅我的问题的人!