知方可補(bǔ)不足~Sqlserver發(fā)布訂閱與sql事務(wù)的關(guān)系
前幾講說(shuō)了一下通過(guò)sqlserver的發(fā)布與訂閱來(lái)實(shí)現(xiàn)數(shù)據(jù)的同步,再通過(guò)EF這個(gè)ORM架構(gòu)最終實(shí)現(xiàn)架構(gòu)系統(tǒng)的讀寫(xiě)分離,而在使用發(fā)布與訂閱來(lái)實(shí)現(xiàn)數(shù)據(jù)同步時(shí),需要我們注意幾點(diǎn),那就是當(dāng)操作被使用在“事務(wù)上下文”時(shí),你的同步操作有可能會(huì)被延時(shí),嘟嘟!
這個(gè)不難理解,我們都知道事務(wù)有一些級(jí)別,而最高級(jí)別serializable 又是.net TransactionScope默認(rèn)的級(jí)別,所以,在程序開(kāi)發(fā)中,只要用了事務(wù),基本都是serializable,而這個(gè)級(jí)別是最安全的,當(dāng)然對(duì)于SQL來(lái)說(shuō),也是最容易發(fā)生死鎖及阻塞的,呵呵。
如果對(duì)要SQL鎖不清楚的同學(xué),可以看我的這篇文章《知方可補(bǔ)不足~Sqlserver中的幾把鎖和.net中的事務(wù)級(jí)別》
下面是我總結(jié)的,在事務(wù)為serializable級(jí)別,對(duì)于發(fā)布訂訂閱同步的關(guān)系
set transaction isolation level serializable begin tran select * from User_Info --讀取所有數(shù)據(jù),等待事務(wù)結(jié)束后才能同步 TAB(S) ,TAB(IX) update User_Info set Status=1 where UserInfoID=1 --更新其他數(shù)據(jù),可以立即同步 TAB(IX),Page(IX),Key(X) select * from User_Info where UserInfoID=1 --事務(wù)中讀取其他數(shù)據(jù),可以立即同步 TAB(IS),KEY(S),Page(IS) select * from User_Info where UserInfoID=28 --事務(wù)中讀當(dāng)前數(shù)據(jù),等待事務(wù)結(jié)束后才能同步 TAB(IS),KEY(S),Page(IS) select * from User_Info where UserInfoID<30 --事務(wù)中讀取范圍數(shù)據(jù),包括要同步的數(shù)據(jù),等待事務(wù)結(jié)束后才能同步,tab(is), KEY(ranges-s),page(is) select * from User_Info where UserInfoID<10 --事務(wù)中讀取范圍數(shù)據(jù),不包括要同步的數(shù)據(jù),可以立即同步,tab(is), KEY(ranges-s),page(is) waitfor delay '00:02:00' --等待2分鐘 commit tran
通過(guò)上面的結(jié)果,我們可以知道,只要當(dāng)前需要同步(正在發(fā)生變化的數(shù)據(jù),就是要同步的數(shù)據(jù))的數(shù)據(jù)不在被鎖的范圍里,就不會(huì)對(duì)同步有所影響,當(dāng)然,你要是在事務(wù)里來(lái)個(gè)select * from table,那你就玩完了,需要等待你的事務(wù)結(jié)束后,你這個(gè)張表發(fā)生變
化的數(shù)據(jù)才能被同步,所以,經(jīng)驗(yàn)告訴我們,在事務(wù)里,能不寫(xiě)查詢就不要寫(xiě),呵呵。
下面圖中顯示的是在一個(gè)事務(wù)里添加了范圍鎖的例子,看上支挺恐怖的,它對(duì)應(yīng)的語(yǔ)句是select * from User_Info where UserInfoID<10,直接查詢出10條數(shù)據(jù),這時(shí),SQL會(huì)把這10條數(shù)據(jù)分別加上范圍共享鎖,以對(duì)這10條數(shù)據(jù)進(jìn)行保護(hù),你此時(shí),要想對(duì)這10條數(shù)據(jù)的任何一條進(jìn)行修改,那只能等待事務(wù)結(jié)束后了......
浙公網(wǎng)安備 33010602011771號(hào)