​回到目录​

前几讲说了一下通过sqlserver的发布与订阅来实现数据的同步,再通过EF这个ORM架构最终实现架构系统的读写分离,而在使用发布与订阅来实现数据同步时,需要我们注意几点,那就是当操作被使用在“事务上下文”时,你的同步操作有可能会被延时,嘟嘟!

这个不难理解,我们都知道事务有一些级别,而最高级别serializable 又是.net TransactionScope默认的级别,所以,在程序开发中,只要用了事务,基本都是serializable,而这个级别是最安全的,当然对于SQL来说,也是最容易发生死锁及阻塞的,呵呵。

如果对要SQL锁不清楚的同学,可以看我的这篇文章《​​知方可补不足~Sqlserver中的几把锁和.net中的事务级别​​》

下面是我总结的,在事务为serializable级别,对于发布订订阅同步的关系

set transaction isolation level serializable 
begin tran
 
select * from User_Info               --读取所有数据,等待事务结束后才能同步 TAB(S) ,TAB(IX)    
update User_Info set Status=1 where UserInfoID=1 --更新其他数据,可以立即同步  TAB(IX),Page(IX),Key(X)
select * from User_Info where UserInfoID=1 --事务中读取其他数据,可以立即同步 TAB(IS),KEY(S),Page(IS)
select * from User_Info where UserInfoID=28 --事务中读当前数据,等待事务结束后才能同步   TAB(IS),KEY(S),Page(IS)
select * from User_Info where UserInfoID<30 --事务中读取范围数据,包括要同步的数据,等待事务结束后才能同步,tab(is), KEY(ranges-s),page(is)
select * from User_Info where UserInfoID<10 --事务中读取范围数据,不包括要同步的数据,可以立即同步,tab(is), KEY(ranges-s),page(is)

waitfor delay '00:02:00' --等待2分钟
commit tran

通过上面的结果,我们可以知道,只要当前需要同步(正在发生变化的数据,就是要同步的数据)的数据不在被锁的范围里,就不会对同步有所影响,当然,你要是在事务里来个select * from table,那你就玩完了,需要等待你的事务结束后,你这个张表发生变

化的数据才能被同步,所以,经验告诉我们,在事务里,能不写查询就不要写,呵呵。

下面图中显示的是在一个事务里添加了范围锁的例子,看上支挺恐怖的,它对应的语句是select * from User_Info where UserInfoID<10,直接查询出10条数据,这时,SQL会把这10条数据分别加上范围共享锁,以对这10条数据进行保护,你此时,要想对这10条数据的任何一条进行修改,那只能等待事务结束后了......

知方可补不足~Sqlserver发布订阅与sql事务的关系_.net

​回到目录​

作者:仓储大叔,张占岭,
荣誉:微软MVP