解決大量更新引起同步鏈延時問題

2021-09-21 05:23:48 字數 3732 閱讀 4950

原文:

解決大量更新引起同步鏈延時問題

前言:

在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的 同步的模式,下圖中的三個按鈕很重要,是我們同步的三個主要按鈕。這個藍色的按鈕 這個灰色的按鈕 下面重點說一下衝突。有以下幾個解決方法。第一,如果自己改的並不多,而...