我们公司最近遇到了 SQL Server 数据库问题,负载过高,一些数据库监控脚本杀死了许多连接。
当发生这种情况时,正在进行的几个事务无法完成回滚。
他们反复说在 pid 上执行 kill 时回滚完成度为 0%。
在网上搜索后,我们发现有人建议重启 SQL Server。由于这是一个生产数据库,所以这并不可取。我们还担心重启可能会导致数据库损坏,迫使我们从备份中恢复。
我们最终重新启动了服务器,并且一切都启动正常,没有回滚的交易。
我的问题是:
是否有可能从一开始就防止这种情况发生?如果没有,有什么方法可以知道重新启动是否安全?
答案1
首先回答你的最后一个问题,你能否保证这种情况不会再次发生?不,确实不会。
实际情况是,当进程被终止时,SQL Server 会告诉客户端该进程已被终止。在某些情况下,SQL Server 会在尝试告诉客户端该进程已被终止时挂起。通常这不是问题,但有时会导致此问题。
如果让进程继续运行,则不会发生任何事情,除了 SPID 仍在进程中。回滚实际上已完成。清除 SPID 的唯一方法是重新启动 SQL 实例。发生这种情况后,重新启动 SQL 实例不会造成损坏。
答案2
我只能说要做好基本工作。首先要知道服务器上当前运行的脚本的重要性。复杂的脚本会消耗太多内存,并且可能会导致数据丢失,因此在运行脚本之前“必须”先执行备份程序。假设计划在无人值守的情况下运行一个千行脚本,那么必须建议开发该脚本的技术人员在其脚本中包含自动差异备份,以确保如果脚本崩溃,至少可以先获得可靠的备份。
如果脚本没有自动备份程序,那么技术人员必须负责在某个预定时间手动执行备份。唯一需要考虑的是知道脚本何时开始在服务器上运行,以便 dba 也知道何时启动手动备份过程。这就是 dba 存在的原因之一。