sql server事务全攻略(转载)
<table id="layoutManager" cellspacing="0" cellpadding="0"> |
<p style="FONT-SIZE: 10pt">原子性
0 begin waitfor delay '00:00:10' print '不重复读' select * from table1 end
0 ? ? ? ? ? ? ? begin ? ? ? ? ? ? ? ? print ? 'insert ? error' ? ? ? ? ? ? ? ? rollback ? ? ? ? ? ? ? end ? ? ? ? ? set ? @i=@i+1 ? ? ? commit ? ? end ? ? go ? ? ? ? ? ? ? 如果两个session同时执行这段话,肯定会在update何insert出现大量的错,这是因为这两个事务开始的时候,都是以select开始的,所以加的都是共享锁,所以导致两个事务读出来的有可能是同一个数,从而在在update何insert时会发生违反主键约束的错误。 ? ? ? ? 但是,只需把select和update换一下位置,就可以保证不发生上述情况,见下 ? ? create ? table ? table1 ? (s_id ? int ? primary ? key) ? ? create ? table ? table2 ? (n_id ? int ? primary ? key) ? ? insert ? into ? table1 ? values ? (1) ? ? go ? ? declare ? @i ? int ? ? declare ? @n_id ? int ? ? set ? @i=0 ? ? while ? (@i<5000) ? ? begin ? ? ? begin ? tran ? ? ? ? ? ? ? update ? table1 ? set ? s_id=s_id+1 ? ? ? ? ? if ? @@error<>0 ? ? ? ? ? ? begin ? ? ? ? ? ? ? ? print ? 'update ? error' ? ? ? ? ? ? ? ? rollback ? ? ? ? ? ? end ? ? ? ? ? select ? @n_id=s_id ? from ? table1 ? ? ? ? ? ? insert ? into ? table2 ? values ? (@n_id) ? ? ? ? ? if ? @@error<>0 ? ? ? ? ? ? ? begin ? ? ? ? ? ? ? ? print ? 'insert ? error' ? ? ? ? ? ? ? ? rollback ? ? ? ? ? ? ? end ? ? ? ? ? set ? @i=@i+1 ? ? ? commit ? ? end ? ? go ? ? ? ? ? 互换了一下位置,就不会出现select取重号的问题,这是事务先进行的是update语句,而update会加一个排他锁,这是很关键,因为它不会像select的共享锁一样,用完会释放,排他锁会一直维持到事务的结束(当然这种排他锁是在同一资源上的排他锁,而不是转化成了完全的事务锁,否则就蜕化成了serializable了),所以实际上,在update之后的select还是有排他锁保护的,所以不会出现重号的问题。 ? ? ? 可见在sql中锁的概念并不只限于资源锁,而是可以延伸到事务层面的事务锁。 ? ? ? ? ? 当然我不知道,这是sql在事务serializable和资源锁之间的一种故意的灵活性,还是出于一些别的目的,或者在别的方面还有更更加明显的体现或作用。 ? ? 可以肯定的就是利用这种锁的机制,改变update何select的顺序,起到的效果比serializable要好得多,因为没有在一些没必要顺序化的语句间保持顺序,而是在需要保证资源一致性的地方用了顺序处理,而在涉及不同资源的时候发挥了并发的特点,可以说是最有效的一种解决方案。??
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!