前面的推文我们掌握了JVM调优技术。今天给大家分享MS SQL数据库监控与调优技术。后续文章都会系统分享干货,带大家从0到1学会性能测试。
死锁有时也称为抱死,不只是关系数据库管理系统,任何多线程系统上都会发生死锁,并且对于数据库对象的锁之外的资源也会发生死锁。例如,多线程操作系统中的一个线程要获取一个或多个资源(例如,内存块)。如果要获取的资源当前为另一线程所拥有,则第一个线程可能必须等待拥有线程释放目标资源,这就是说,对于该特定资源,等待线程依赖于拥有线程,在数据库引擎实例中,当获取非数据库资源(例如,内存或线程)时,会话会出现死锁。
SQL Server中有一个锁管理器负责检测死锁,当检测到死锁时,为了打破死锁,锁管理器会选择一个SPID作为牺牲者,锁管理器会取消牺牲SPID当前的批作业,回滚它的事务。
如果经常出现死锁,那么数据库的性能将会受到影响,通过配置SQL Server Profiler跟踪,可以捕获数据库列锁事件的相关信息并进行分析。
关于死锁跟踪,应该包含以下事件的设置,如图11-24所示:
1)Locks-Deadlock graph:提供死锁的XML描述,这个类和Lock:Deadlock事件类同时发生;
2)Locks-Lock:Deadlock:标识哪个SPID被选为死锁牺牲者;
3)Locks-Lock:Deadlock Chain:监控死锁状况何时发生;
4)Stored Procedures-RPC:Completed:指示一个远程过程调用已经完成;
5)TSQL-SQL:BatchCompleted:指示Transact-SQL批作业已经完成;
实例:创建一张如图11-18所示的简单在表结构,接下来使用脚本来触发死锁,打开一个查询窗口(查询1),输入以下代码:
use test
set nocount on
select @@spid as spid
begin tran
update test
set name = 'efg123'
where id = 1
waitfor delay '00:0:30'
update test
set name = 'abc456'
where id = 2
以上代码,在一个事务中有两个T-SQL UPDATE语句,第一UPDATE语句是修改ID号为1的数据行,并等待30秒,第二个UPDATE修改ID号为2的数据行,暂时先不执行这段代码。
在打开另一个查询窗口(查询2)并输入以下代码:
use test
set nocount on
select @@spid as spid
begin tran
update test
set name = 'abc456'
where id = 2
waitfor delay '00:0:30'
update test
set name = 'efg123'
where id = 1
这段代码的逻辑以第一个查询窗口类似,第一UPDATE语句是修改ID号为2的数据行,并等待30秒,第二个UPDATE修改ID号为1的数据行,暂时先不执行这段代码。
现在执行如下步骤:
1) 配置好SQL Server Profiler并启动;
2) 执行查询1窗口中的代码;
3) 在查询1窗口开始执行的30秒时间内,执行查询2中的代码。
查询1执行的结果如图11-25所示,本实例中SPID号为54。
图11-25 查询1执行的结果
查询2执行的结果如图11-26所示
查询2执行时,显示如下错误信息:
消息1205,级别13,状态45,第5 行
事务(进程ID 53)与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品,请重新运行该事务。
SQL Server Profiler捕获到的死锁事件信息,如图11-27所示
在死锁图中,显示了SPID53是牺牲者,并且被删除,当光标移动圆圈内时,会显示所执行的语句。
如果对上例的查询语句进行修改,使两次更新ID号的顺序一致,那么则不会发生死锁现象。
下期分享SQL Profiler识别长时间查询知识,敬请关注!