警告:这个悲惨故事包含代码异味和糟糕的设计决策以及技术债务的示例。
如果您熟悉 SOLID 原则,请练习 TDD 并对您的工作进行单元测试,请勿继续阅读。除非你想对某人的不幸大笑,并为自己的伟大而幸灾乐祸,因为你知道你永远不会为你的继任者留下如此巨大的一堆废话。
所以,如果你坐得舒服,那我就开始。
在过去 7 个月里我继承并支持和修复错误的这个应用程序中,一个 6 个半月前离开的开发人员给我留下了一个令人毛骨悚然的问题。是的,在我开始后 2 周。
反正。在这个应用程序中,我们有clients
,employees
和visits
表。
还有一个称为AppNewRef
(或类似名称)的表...等待它...包含用于其他每个表的下一个记录 ID。因此,可能包含以下数据:-
TypeID Description NextRef
1 Employees 804
2 Clients 1708
3 Visits 56783
当应用程序为 创建新行时Employees
,它会在AppNewRef
表中查找,获取值,使用该值作为 ID,然后更新NextRef
列。Clients
和Visits
所有其他要使用的表都NextID
存储在这里。
是的,我知道,这个数据库上没有自动编号IDENTITY
列。一切都是以“当它是一个 Access 应用程序时”为借口。这些 ID 保存在 (VB6) 代码中。因此,最多可能有 20 亿条 1.47 亿条记录。好的,这似乎工作得很好。(除了应用程序正在更新和处理锁定/更新等,而不是数据库的事实)
因此,我们的用户非常高兴地创建Employees
,Clients
等Visits
。Visits ID
每次稳定增加几十个。然后问题就发生了。我们的客户端在创建批量访问时导致数据库损坏,因为服务器正在很好地运行,并且应用程序变得无响应。所以他们使用任务管理器杀死应用程序,而不是耐心等待。当然,该应用程序似乎确实被锁定了。
继续到今年早些时候,开发人员 Tim(真实姓名。此处不保护有罪者)开始修改代码以分阶段进行批量更新,以便 UI 保持“响应式”。然后四月来了,他正在处理他的通知(你现在可以想象这个场景,不是吗?)他正在忙着完成更新。
4 月底和 5 月初,我们更新了一些客户。在接下来的几个月中,我们会更新越来越多的内容。
在蒂姆(真名,记住)和我(蒂姆离开前两周开始)以及一周后开始的另一位新开发人员看不见的情况下,访问表中的 ID 开始大幅上升。巨大的,我的意思是一次10000、20000、30000。有时几十万。
下面的图表说明了使用的 ID 的快速增长。
十一月滚动。客户致电技术支持并报告他遇到了错误。我查看错误消息并询问数据库,以便调试代码。我发现这个值太长了。我做了一些查询,提取信息,将其放入 Excel 并绘制图表。
我不认为让代码处理任何长于 ID 的东西是正确的方法,因为这个应用程序将该 ID 传递到其他 DLL 和 OCX 并破坏那些接口似乎是一个我没有伤害的整个世界不想现在遇到。
我正在调查的一个潜在想法是尝试修改 ID,以便我可以将它们降低到较低级别。基本上填补了空白。使用ROW_NUMBER
功能
我正在考虑为每个表添加一个新列,这些表具有对这些访问 ID 的外键引用(不是正确的外键,这些约束在此数据库中不存在)。这个新列可以存储访问 ID 的旧(当前)值(哦,只是为了混淆事物;在某些表上它被称为EventID
,而在某些表上它被称为VisitID
)。
然后,对于引用 that 的每个其他表VisitID
,更新为新值。
想法?建议?T-SQL 的片段帮助大家感激不尽。