SQL Server 2014如何提升非在线的在线操作
在今天的文章里,我想談下在線索引重建操作(?Online Index Rebuild operations),它們在SQL Server 2014里有怎樣的提升。我們都知道,自SQL Server 2005開始引入了在線索引重建操作。但這些在線操作并非真正的在線操作,因為在操作開始時,SQL Server需要獲得共享表鎖(Shared Table Lock (S)?),在操作結束時需要在對應表上獲得架構修改鎖(Schema Modification Lock (Sch-M)?)。因此這些操作是真正的在線操作,只是營銷技巧(marketing trick)。但是,親,“在線”肯定比“部分在線”好聽多了。
盡管如此,SQL Server 2014還是在在線索引重建的開始和結束發生的阻塞做了一些改進。因此,在你執行在線索引重建時,你可以定義所謂的鎖優先級(Lock Priority)。來看看下面的代碼,你會看到起作用的新語法:?
1 ALTER INDEX idx_Col1 ON Foo REBUILD 2 WITH 3 ( 4 ONLINE = ON 5 ( 6 WAIT_AT_LOW_PRIORITY 7 ( 8 MAX_DURATION = 1, 9 ABORT_AFTER_WAIT = SELF 10 ) 11 ) 12 ) 13 GO當阻塞情況發生時,你可以用WAIT_AT_LOW_PRIORITY關鍵字定義如何處理。使用第1個屬性MAX_DURATION指定你想要等待的時間——這里是分鐘,不是秒!用ABORT_AFTER_WAIT屬性你指定哪個會話需要被SQL Server回滾。SELF意味著那個ALTER INDEX REBUILD語句會回滾,當你指定BLOCKERS時,阻塞的會話會回滾。當然,當沒有阻塞發生時,在線索引重建操作會立即執行。因此這里你只能配置當阻塞情況發生時要怎么處理。
好了,我們來實操下。我們新建一個數據庫,一個簡單的表和一個聚集索引。?
1 -- Creates a new database 2 CREATE DATABASE Test 3 GO 4 5 -- Use the database 6 USE Test 7 GO 8 9 -- Create a simple table 10 CREATE TABLE Foo 11 ( 12 Col1 INT IDENTITY(1, 1) NOT NULL, 13 Col2 INT NOT NULL, 14 Col3 INT NOT NULL 15 ) 16 GO 17 18 -- Create a unique Clustered Index on the table 19 CREATE UNIQUE CLUSTERED INDEX idx_Col1 ON Foo(Col1) 20 GO 21 22 -- Insert a few test records 23 INSERT INTO Foo VALUES (1, 1), (2, 2), (3, 3) 24 GO?為了觸發阻塞,我在不同的會話開始一個新的事務,但不提交:
1 BEGIN TRANSACTION 2 3 UPDATE Foo SET Col2 = 2 4 WHERE Col1 = 1這意味著我們在需要修改的記錄上獲得排它鎖(Exclusive Lock (X)),在對應的頁上獲得意向排它鎖(Intent-Exclusive Lock (IX)),在表本身獲得意向排它鎖(Intent-Exclusive Lock (IX))。我們剛剛在SQL Server里創建了典型的鎖定層次(locking hierarchy):表=>頁=>記錄。在表級別的意向排它鎖(IX Lock)和在線索引重建操作需要的共享鎖(Shared Lock)是不兼容的——典型的鎖/阻塞情形發生了。當你現在執行在線索引重建操作時,會發生阻塞:
?
1 ALTER INDEX idx_Col1 ON Foo REBUILD 2 WITH 3 ( 4 ONLINE = ON 5 ) 6 GO?
當你查看DMV?sys.dm_tran_locks時,你會看到那個需要共享鎖(Shared Lock(S))的會話需要等待。這個會話會永遠等待。我剛才就說過:“部分在線”……
1 SELECT * FROM sys.dm_tran_locks當我們執行帶有鎖優先級(Lock Priority)的在線索引重建時,有趣的事情發生了:?
1 -- Perform an Online Index Rebuild 2 ALTER INDEX idx_Col1 ON Foo REBUILD 3 WITH 4 ( 5 ONLINE = ON 6 ( 7 WAIT_AT_LOW_PRIORITY 8 ( 9 MAX_DURATION = 1, 10 ABORT_AFTER_WAIT = SELF 11 ) 12 ) 13 ) 14 GO
在這個情況下,我們的ALTER INDEX語句會等待1分鐘(MAX_DURATION),然后語句本身取消了(ABORT_AFTER_WAIT)。
如果你在這里指定了BLOCKERS選項,那么阻塞的會話就會回滾。當我們同時(在1分鐘期間)查看DMV?sys.dm_tran_locks,我們看到了有趣的東西:
?
從圖中可以看到,SQL Server這里請求一個LOW_PRIORITY_WAIT的狀態。因此3個請求狀態(GRANT,WAIT,CONVERT)有了第4個選項:LOW_PRIORITY_WAIT。當我們查看DMV?sys.dm_os_waiting_tasks時,事情變得有意思(59是執行語句的會話ID):
1 SELECT * FROM sys.dm_os_waiting_tasks WHERE session_id='59'在線索引重建操作的等待會話報告了一個新的等待類型LCK_M_S_LOW_PRIORITY。這意味著當在線索引重建操作被阻塞時,我們可以從服務器級別(sys.dm_os_wait_stats)的等待統計信息里獲得——不錯!
但是LCK_M_S_LOW_PRIORITY并不是新的等待類型。在SQL Server 2014里,當你查看DMV?sys.dm_os_wait_stats時,會看到21個新的等待類型:
1 SELECT * FROM sys.dm_os_wait_stats WHERE wait_type LIKE '%LOW_PRIORITY%'- LCK_M_SCH_S_LOW_PRIORITY
- LCK_M_SCH_M_LOW_PRIORITY
- LCK_M_S_LOW_PRIORITY
- LCK_M_U_LOW_PRIORITY
- LCK_M_X_LOW_PRIORITY
- LCK_M_IS_LOW_PRIORITY
- LCK_M_IU_LOW_PRIORITY
- LCK_M_IX_LOW_PRIORITY
- LCK_M_SIU_LOW_PRIORITY
- LCK_M_SIX_LOW_PRIORITY
- LCK_M_UIX_LOW_PRIORITY
- LCK_M_BU_LOW_PRIORITY
- LCK_M_RS_S_LOW_PRIORITY
- LCK_M_RS_U_LOW_PRIORITY
- LCK_M_RIn_NL_LOW_PRIORITY
- LCK_M_RIn_S_LOW_PRIORITY
- LCK_M_RIn_U_LOW_PRIORITY
- LCK_M_RIn_X_LOW_PRIORITY
- LCK_M_RX_S_LOW_PRIORITY
- LCK_M_RX_U_LOW_PRIORITY
- LCK_M_RX_X_LOW_PRIORITY
所有主要的等待類型(LCK_M_*)都有額外的鎖優先級等待類型。這個非常酷,也非常強大,因為你很容易從中可以跟蹤到為什么在線重建索引操作被阻塞。另外,對于分區切換(Partition Switching)也適用同樣的技術(鎖優先級(Lock Priorities)),因為在切換期間,操作也要在2個表(原表,目標表)上獲取架構修改鎖(Schema Modification Lock (Sch-M))。
我希望這篇文章可以讓你理解SQL Server 2014里的鎖優先級(Lock Priorities),還有為什么SQL Server里的“在線”操作實際上只是“部分在線”。
感謝關注!
posted on 2015-07-07 09:47 NET未來之路 閱讀(...) 評論(...) 編輯 收藏轉載于:https://www.cnblogs.com/lonelyxmas/p/4626082.html
總結
以上是生活随笔為你收集整理的SQL Server 2014如何提升非在线的在线操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我对NHibernate的感受(3):有
- 下一篇: PL/SQL NOCOPY限制模式