SQLServer中几种典型的等待
SQLServer 中涉及等待的情况很多,产生等待的原因也很多,但最终归纳起来可以看作是两种,一种是资源等待,例如I/O阻塞、网络阻塞、锁定阻塞等等,另一种是CPU等待。本文将会讨论这些等待类型的特点、原因及解决方法。
1.锁定等待
锁定阻塞等待是SQLServer中最常见的等待类型之一。在数据库操作的过程中,由于数据的并发访问,在进行修改的时候,我们需要获取这条记录的锁定,保证数据在修改期间不会被其他用户查到。但是因为不同用户之间操作的并发性,就会出现一个用户等待其他用户完成任务的情况。
在SQLServer的锁定等待中,主要涉及两种锁定,分别是共享锁定和排它锁定。在某个时刻只有一个事务可以获取排它锁定而进行修改工作。如果在此期间有其他事务需要访问该记录,它会等待锁定被释放。
一个等待的事务将会阻塞其他需要请求相同资源的事务,而又导致了更多的等待。当这个问题无法解决时,整个系统的性能受到影响。
解决办法是调整访问模式,也就是修改锁定模式。
--权衡多个实例之间的用户并发性,提高性能
select * from table where columnname = 'xxx' with (NOLOCK);
--暴力,比如用在线运维脚本,杀死等待后续会谈到的锁定进程(sp_lock2可查)
kill 50;
2.磁盘I/O等待
SQLServer中的磁盘I/O等待是比较常见的等待类型之一。如果查询的数据量较大,或者是从磁盘中读取非常耗时的内存,那么就会产生等待。
减少顺序扫描、减小读入的数据量,加快磁盘I/O的速度是解决这个问题的关键。增加缓存区域,避免同样的数据被重复读取,这可以由SQLServer的压缩方式来解决。
--增加缓存区域
USE MASTER;
GO
EXEC sp_configure 'max server memory (MB)', 512;
RECONFIGURE WITH OVERRIDE;
GO
--开启必要压缩
ALTER DATABASE [DBName] SET COMPATIBILITY_LEVEL = 130;
GO
ALTER DATABASE [DBName] SET PAGE_VERIFY NONE;
GO
ALTER DATABASE [DBName] SET RECOVERY SIMPLE WITH NO_WAIT;
GO
BACKUP DATABASE [DBName] TO DISK = N'\\Blob02\SQLBackups\Path\2019_06_07_15_48_32\DBName.bak' WITH NOFORMAT,
NOINIT, NAME = N'DBName-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10
GO
3.网络等待
在SQLServer中访问网络通常意味着等待网络结果的时间。如果网络传输的速度较慢,那么就会产生等待。这种等待通常是由服务器与客户端之间的网络通信引起的。
解决该问题的方法是优化SQL语句,在SQL Server中充分使用分布式查询技术。但是这种优化需要更加复杂的系统环境来支持,因为它需要大量使用客户端和服务器的存储资源和处理资源,这会导致对一些已经压力过大的系统性能的影响。
4.CPU等待
在SQLServer的等待中,CPU等待是其中一个非常不幸的种类,因为它是异步的,并且难以监控和控制。如果系统中的CPU负载高,那么就会导致CPU的等待。
在SQLServer的客户端-服务器体系结构中,客户端是有限的,而服务器的应用程序却经常需要在处理多个请求时同时保持对其他资源的访问,因此,SQLServer需要处理复杂的事务排队和处理过程。
优化SQL的目的是避免发生CPU等待。在SQLServer中使用分析器工具可以更加容易地检查SQL是否优化,或重构SQL
通过优化或重构SQL语句来提高系统整体性能。
5.锁定超时
锁定超时会出现在由于连接非法等原因导致系统没有锁定资源时被抛出。
解决这个问题的方法也比较简单,就是在请求锁定资源时加入超时机制控制。如果等待时间过长(超过预设时间),则需要重新检查锁定的资源。
--加入超时机制
SET LOCK_TIMEOUT 500; -- 设置超时时间为500ms
BEGIN TRANSACTION --开始事务
SELECT columnname FROM table WHERE name = 'xxx'; --查询资源
UPDATE table SET columnname = 'yyy' WHERE name = 'xxx'; --锁定资源并修改
COMMIT; --提交事务
6.内存等待
SQLServer中的内存等待通常是由SQLServer从磁盘中读取数据并将其存储在内存中导致的。在读取查询数据的过程中,如果没有足够的内存可用,SQLServer将会在内存中维护查询数据,并在磁盘上读取数据。这种等待通常被称为内存等待。
内存等待问题可以通过在服务器上增加RAM解决。如果增加了RAM却没有解决问题,那么需要审查使用的索引和缓存,以优化查询和对象访问。
采用不同的数据分析方法,例如在SQLServer中使用行池技术,也是增加缓存区域的另一种方法。
7.线程/任务等待
线程等待是指由于系统繁忙,导致某些任务需要等待其他任务完成之后才能继续。在SQLServer的开发过程中,可能会遇到一些较为复杂的任务,例如需要更长时间的任务进行数据挖掘或适配。
这种等待的解决方法是分配更多的工作线程。而SQLServer的优秀系统设计可支持分布式任务负载均衡,提高任务执行的效率。
在SQLServer中,Max Worker Count的最大值为2或者4,因此可以通过提高Max Worker Count的值来改善CPU的使用率。
USE master
go
EXEC sp_configure 'max degree of parallelism', '12';
reconfigure
go
总结
SQLServer中的等待类型很多,但大致可以分为七种。每个等待类型通常涉及一些特定的资源,例如锁定、I/O、网络、CPU、内存、任务线程。在纠正对应等待情况时,可以针对具体问题实施相应的解决方法。