今天处理了一个问题,因为sql server数据库查询阻塞引起的。
首先,在数据库上面查看,存在大量的阻塞:
SELECT a.blocking_session_id, a.wait_duration_ms, a.session_id,b.text
FROM sys.dm_os_waiting_tasks a,
(SELECT t.text ,c.session_id
FROM sys.dm_exec_connections c
CROSS APPLY sys.dm_exec_sql_text (c.most_recent_sql_handle) t) b
WHERE a.session_id = b.session_id and a.blocking_session_id IS NOT NULL
从查询的结果来看,均是select阻塞,然后对该select 语句对某个大表进行全表扫描,长时间进行,阻塞其它会话,使得数据库性能极具下降!从活动会话分析来看,占用了大量cpu。
出现这种情况,主要是由于sql server的封锁机制引起的。
sql server的隔离级别分为两种,这两种隔离级别都是通过行版本控制在tempdb中生成数据的复本来解决数据的写和读的时候发生锁及阻塞的问题的。不过snapshot isolation需要在数据库中执行
ALTER DATABASE Aesop SET ALLOW_SNAPSHOT_ISOLATION ON
之后,然后在执行事务之前,设置连接的隔离级别
SET TRANSACTION ISOLATION LEVEL Snapshot;
BEGIN TRAN
SELECT Title
FROM FABLE
WHERE FableID = 2
这时候当发生第二个事务对fableid=2的行进行更新的时候,它可以进行更新,但是在更新事务提交之后,查询事务依然是无法查到更新事务所做的修改,它还是只能查询到原始的数据,这种情况类似于repeatable read隔离级别,但是在repeatable read下,更新事务是无法更新的,直到查询事务提交之后才可以。有的类似oracle的脏读机制。
Read Committed Snapshot Isolation只是针对sqlserver默认的read committed隔离级别的。使用它需要执行如下sql:
ALTER DATABASE Aesop SET READ_COMMITTED_SNAPSHOT ON;
如果数据库只是普通的read committed级别下,当执行一个更新事务但没有提交时,再执行一个对更新数据进行查询的事务,查询事务将无法查询,被阻塞,但是在 READ_COMMITTED_SNAPSHOT被打开的情况下,在上面那种情况中,查询事务将不会被阻塞,它能够查询到未更新前的数据。
Snapshot Isolation是针对SET TRANSACTION ISOLATION LEVEL Snapshot;的,在使用的时候需要在事务前设置隔离级别,而Read Committed Snapshot Isolation完全不需要使用set transaction isolation,因为它是针对数据默认的read committed隔离级别的。
而本数据库是采用的off,所以才出现以上的这种情况。跟开发商沟通后,他们认为不能开启,会影响业务!
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29371470/viewspace-1270079/
,如需转载,请注明出处,否则将追究法律责任。