原文:
解決大量更新引起同步鏈延時問題
前言:
在sqlserver資料庫中,當我們對乙個位於同步鏈上的表進行更新時,如果更新的記錄數也非常多,幾百或是幾千萬,那麼批量更新該錶會造成同步鏈的大量延時(甚至有可能崩潰掉,即使同步鏈不崩潰,等的人也要崩潰了)。
原因:
一般情況下,replication是根據我們更改的資料一條條更改記錄的,也就是說我們在發布端下達如下的語句:
update
testtb
settt=
'***x'
where ustate=0
如果這條更新語句,修改的資料量是一千萬條的話,那replication同步鏈需要傳遞一千萬條如下的語句到訂閱端去執行:
exec
[dbo].[sp_msupd_dbo
testtb
]default
,'***x'
,default
,2,0x02
如果我們有8臺訂閱端,而我們更新的資料也不是這麼簡單的資料的話(如更新一些nvarchar(1000)之類的),這個資料流量是非常恐怖的。
解決辦法:
基於以上原因,我們在對同步鏈上的表進行大規模更新操作時,必須要非常小心,避免資料的大量更新;但是如果業務有此要求,必須要在同步的表上更新這麼多資料量,如何辦呢?
1.如果你已經在發布端直接執行了類似上面的語句,那就只有乙個字:「等」(當然也可以將表從同步鏈中去掉);
2.我們可以採用分批處理的方式來更新同步鏈,一批次處理幾百或者一千條資料,處理完一批後,等待10s鐘,再執行下一批,類似語句如下(常用):
declare
@count int
,@sumcount int
,@subcount int
set@sumcount=0
set@subcount=0
select
@count=
count
(0)from
testtb where ustate=0
where
ustate=0
while
(@sumcount= 1000)
begin
update
top
(1000) testtb
set tt=
'***x'
where ustate=0
set @subcount=
@@rowcount
set @sumcount=@sumcount+1000
waitfor
delay
'00:00:10'
end
3.如果更新的資料很大,用第二種方法將會消耗很長的時間,等不起呀;有沒有更好的方法呢?我們可以通過使用臨時儲存過程來更新資料,下面我們通過乙個例項來看看如何操作:
--新建乙個測試表
create
table testtb
( id int
identity
(1,1)
primary
key,
,name varchar
(20)
,ustate smallint)
--插入測試資料
insert
into testtb(name,ustate)
values
('aaaaa'
,0),
('bbbbb'
,1),
('ccccc'
,0),
('ddddd'
,1),
('eeeee'
,0),
('fffff',1)
--新建乙個儲存過程
create
proc usp_updatetesttb
as begin
update testtb set name=
'kkkkkk'
where ustate=1
end
我們把錶testtb 和 usp_updatetesttb 都建到同步鏈上,需要注意的是,testtb表結構在訂閱端需要將identity 屬性去掉;usp_updatetesttb需要選擇同步更改和執行,即將同步的replicate屬性 選為「execution of the stored procedure」,這樣在發布端執行儲存過程時,訂閱端也會執行相應的儲存過程,而不是分條執行儲存過程中影響的每一條語句;
同步建好後,我們在訂閱端開啟profile,選擇我們要跟蹤的庫,然後在訂閱端做以下測試:
--先查下滿足記錄的條數
--直接執行更改語句
update testtb set name=
'pppppp'
where ustate=1
(3 row(s) affected)
--更改後訂閱端的資料
我們到訂閱端的profile中去看看傳遞過來的語句情況:
可以看到有三條語句傳過來了;
接下來我們執行儲存過程usp_updatetesttb,這個sp也是更新testtb中三條資料,我們看看profile中又有什麼資訊
--發布端執行
usp_updatetesttb
exec
usp_updatetesttb
(3 row(s) affected)
--訂閱段資料
訂閱端profile的資料:
圖中我們可以看到,訂閱端也只是執行了usp_updatetesttb這個儲存過程,並不會傳遞三條修改的記錄過來,如果這個sp更新的資料很大,這樣將大大減少同步鏈傳遞的資料量(如果我們更改的記錄是一千萬,傳遞的也就一條命令),資料的更新只相當於本地庫的更新,對同步鏈沒有影響;同時,基於對系統影響的考慮,我們把方法二和方法三兩中方法結合起來運用,能收到很不錯的效果。
避免更改引起的大量改動
因為所有的操作最終都作用在基表上,因此基表名和列名的變化會對這些語句產生影響,此時必須修改所有的語句,這樣不但麻煩,有時甚至會發生錯誤。另外,有的甚至表名和列名複雜而晦澀,用起來極不方便。怎樣才能解決這個問題呢?避免直接依賴於基表的問題,方法有 使用檢視為表名和列名起別名,在應用過程中可以借助檢視中...
sqlserver自動收縮資料庫引起大量阻塞
最近遇到乙個資料庫設定了自動收縮,收縮期間引起大量阻塞的問題,記錄下看到的文章學習 隨著資料量的增加資料庫的裝置檔案 mdf ldf 會不斷增長,當資料庫中的某些資料刪除,資料庫裝置檔案的大小並不會隨著資料量的減少而減少,資料庫裝置需要占用的磁碟空間就沒那麼大了,這時候自動收縮就可以釋放出磁碟空間,...
SVN同步,更新,解決衝突的方法
來講一下,我們開發過程中,如何使用svn.如圖,我們一般都是選中專案以後,右鍵 team 與資源庫同步 下面會跳轉到myeclipse的 同步的模式,下圖中的三個按鈕很重要,是我們同步的三個主要按鈕。這個藍色的按鈕 這個灰色的按鈕 下面重點說一下衝突。有以下幾個解決方法。第一,如果自己改的並不多,而...