起初,人们以为这只是个简单的小bug,甚至,在本地都未能复现。

  事情的起因是公司内部提测,A单据生成B单据时,B单据中的价格不是最新。 

  如下图:

  正确的逻辑是A单据生成时,先更新价格,再生成B单据,而B单据中的价格就可以用到更新后的价格。如图1。

  同事A的问题在于,为什么他做单时,先A后B再更新,导致B的价格取值不对。也就是图2。

  经过本地自测,发现我电脑上取值是对的,既然我本地没问题,那就是没问题咯!系不系你们哪里没配置好所以电脑环境有问题呀?

      这个问题验证了好久,最后发现是触发器优先级导致的。

      一张表,有两个update触发器,那么先执行哪个呢?其实看不出来,在数据库里也不方便调试。可能有人会问,为什么搞俩触发器?这其实是历史技术债务问题。

      早先系统就有两个触发器,后来发现顺序不对有bug,解决方案有两种:

      1、合并触发器,使其成为一个,并按指定顺序编写代码逻辑。

      2、设置触发器优先级,指定某个先执行。

      发现问题之初,采用了方案2,因为改动相对简单,无需去合并,合并要考虑的东西多一些。怎么设置优先级看这个:

      https://learn.microsoft.com/zh-cn/sql/relational-databases/system-stored-procedures/sp-settriggerorder-transact-sql?view=sql-server-ver16

      多的先不说,上面的方案中,指定其中一个优先执行,就可以解决我们当时的问题。

      然后离谱的事就来了,同事A后面发现他做单数据不对,后面我核实时,经过多方位分析,发现之前使用的方案2在他们的数据库中未能生效,一时间也不好说是一直没生效还是中途失效了。不过后面经过深入分析,是中途失效了,至于什么原因,刚开始也没摸清,后来知道了,灵感一闪想到的:数据库操作导致方案2失效。

      通过sp_settriggerorder设置的优先级,在SQL Server中是看不出任何痕迹的,这也是最开始我咨询同事为何使用方案2的原因,很难排查。

      那么什么操作能导致设置失效呢?试了新增触发器、修改触发器,都不行,那只能是删除了!没错,设置触发器A为first,再删,再新增,这个设置就失效了。很明显,删了重建,那这中途加的设置自然失效。而存在删除重建这种操作的原因在于系统每次升级时,如果触发器有改动,那么逻辑就是删除重建一个新的。而这,就是原因!

 

  看帖好像很简单,但是排查其实很难,本地是OK的,涉及升级机制,以及触发器施加的优先级无法肉眼查看,这中间难免曲折。

      最后的优化是使用方案1,对触发器进行合并。当然,不建议直接把触发器2的代码Copy到触发器1中,这里我采用的是把触发器2的代码放在新建的存储过程里,再在触发器1里面调用,可最大程度和之前结构类似,无非之前在第二个触发器里,现在在存储过程里,分开写程序的结构清晰些。

 

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。