我维护了一个 MVC 应用程序,其中包含一些长时间运行的批处理过程,用于发送新闻通讯、生成报告等。
我以前遇到过很多死锁问题,其中一个长时间运行的查询可能会在一行上持有锁,然后需要由另一个进程更新。
我最初想出的解决方案是有一个计划任务,它创建数据库快照,就像这样......
CREATE DATABASE MyDatabase_snapshot_[yyyyMMddHHmmss]... AS SNAPSHOT OF MyDatabase
然后我的应用程序有一些逻辑可以找到最新的可用快照,并将其用于长时间运行的进程的只读连接,或者需要只读连接的任何其他地方。
当前设置功能完善且可靠。然而,依赖于该计划任务并不能让我开心。我可以想象,在未来的某个阶段,如果其他人在照顾这个项目,这可能是一个容易引起混淆的问题的来源。例如,如果将数据库移动到另一台服务器,并且未正确设置快照创建计划任务。
从那以后,我意识到我可以通过使用快照事务隔离来获得类似的结果,并避免管理数据库快照的创建和清理的所有额外复杂性。
但是,我现在想知道使用事务执行此操作与继续使用静态快照是否可能存在任何性能缺陷。
考虑以下场景。
该系统会定期向大约 20,000 个订阅者发送个性化的工作列表。对于这些订阅者中的每一个,它都会进行数据库查找以创建匹配的作业列表。
一直在做的事情是遍历完整的收件人列表,并且对于每一个...
- 打开与快照数据库的连接
- 运行查询以查找匹配的作业
- 关闭快照数据库连接
相反,它会执行以下操作...
- 打开与普通数据库的数据库连接(非快照)
- 创建快照隔离事务
- 运行查询以查找匹配的作业
- 关闭交易
- 关闭数据库连接
这实际上会转化为数据库服务器的更多工作吗?
具体来说,我想知道第 2 步涉及到什么。
从应用程序中消除复杂性是一件好事,但不会以牺牲性能为代价。特别是因为这个特定的过程已经是服务器密集型的,并且需要很长时间才能运行。