事务的提交模式(事务的持久特性):1、自动提交模式(一条sql语句就是一个事务 )
2、显示提交模式(要求程序员显示添加begin tran和commit tran/rollback tran,中间添加任意多sql语句)
3、隐式提交模式(begin tran是由dbms发的,commit tran/rollback tran是由程序员显示添加,中间可以添加任意多sql语句,也就是说commit tran/rollback tran的下一句就是一个新事务的开始)
注:在ADO.NET中仅支持自动提交模式(默认模式)和显示提交模式)
在编程中需要考虑的并发冲突有:
1、脏读:读取未提交的数据。一个进程更新了数据但在另一个进程读取相同数据之前未提交该更新。第二个进程所读取的数据处于一种不一致状态。
图1-0(t3时刻事务T2读到了脏数据)
2、丢失修改:一个进程读取了数据,并对数据执行了一些计算,然后根据这些计算更新数据。如果两个进程都是先读取数据,然后再根据他们所读取数据更新,其中一个进程可能会覆盖另一个进程的更新。
图1-1(本身卖完两张票后数据库中A应为0,丢失修改造成A为1)
3、不可重复读:在同一事物的两次读取中,进程读取相同的资源得到不同的值。当第二个进程在第一个进程的两次读取之间更新数据,就会发生这种情况。
图1-2(两次读取不一致数据)
4、幻读:当一个进程对一定范围内的行执行操作,而另外一个进程对该范围内的行执行不兼容的操作,这时会发生幻读。例如,一个进程删除的符合某筛选器的所有行,在删除事务期间,另一个进程插入符合该筛选器的新行。则新行被认为是幻影行。
图1-3
锁:
1、锁的类型:s锁、x锁、u锁(用来解决由于锁转换造成的死锁)
2、锁的范围:行、page、table、db
3、持续时间:x锁和u锁持续时间都是从加锁到事务结束;s锁分为两种情况:在已提交读隔离模式中,一旦读取完成s锁立即释放;在可重复读隔离模式中,持续到事务结束才释放。
4、锁的兼容性:s锁:兼容的锁有:s锁,u锁;不兼容的锁:x锁
u锁:兼容的锁有:s锁;不兼容的锁:u锁,x锁
x锁:兼容的锁有:无 ;不兼容的锁:x锁,s锁,u锁
并发控制模式:悲观控制模式和乐观控制模式。
1、悲观并发控制模式:一个锁定系统,可以阻止用户以影响其他用户的方式修改数据。如果用户执行的操作导致应用了某个锁,只有这个锁的所有者释放该锁,其他用户才能执行与该锁冲突的操作。这种方法之所以称为悲观并发控制,是因为它主要用于数据争用激烈的环境中,以及发生并发冲突时用锁保护数据的成本低于回滚事务的成本的环境中。
2、乐观并发控制模式:在乐观并发控制中,用户读取数据时不锁定数据。当一个用户更新数据时,系统将进行检查,查看该用户读取数据后其他用户是否又更改了该数据。如果其他用户更新了数据,将产生一个错误。一般情况下,收到错误信息的用户将回滚事务并重新开始。这种方法之所以称为乐观并发控制,是由于它主要在以下环境中使用:数据争用不大且偶尔回滚事务的成本低于读取数据时锁定数据的成本。
事务隔离级别:
1、未提交读:使用未提交读隔离级别时,读取器不请求共享锁。因此,它永远不会与修改数据的会话发生冲突。也就是说,他可以读取已经被X锁锁定的数据,不会干扰修改数据的进程。
特点:读取器不请求共享锁(s锁)
用途:在读取“历史”数据(不存在修改的数据)时,用这个隔离级别,提高效率。
能够解决的并发冲突问题:4中并发冲突,一个也不能解决。
2、已提交读:在这种隔离级别下,进程请求一个共享锁以读取数据,一旦读取完数据立即释放,不管事务什么时候结束。
特点:读取器加共享锁(s锁),但读取完数据立即释放。
能够解决的并发冲突问题:脏读
注:sql server默认的隔离级别就是:已提交读。
3、可重复读:在这种隔离级别下,进程也会请求共享锁,但事务保持共享锁直到事务被终止。你可以确保得到可重复读,因为在你的多次读取之间没有其他进程可以获取X锁。
特点:读取器加共享锁(s锁),并且保持共享锁直到事务终止。
能够解决的并发冲突问题:脏读,不可重复读,丢失修改。
注意:在可重复读隔离级别下,丢失修改有可能会造成死锁。例如:如果读取数据的两个进程保持共享锁直到事务结束,这两个进程尝试修改数据会导致死锁,因为每个进程都请求排它锁(X锁),而排它锁被另一个进程阻塞。解决该死锁问题的方法是:给这两个进程加U锁,因为两个u锁之间是互斥的,当一个进程加上u锁后,另外一个进程就加U锁就会被阻塞,这样就不会出现死锁现象。
4、可串行读:在进行操作的表上加共享锁。
特点:在表上加共享锁。
能够解决的并发冲突问题:脏读,不可重复读,丢失修改,幻读。
以上隔离级别均属于悲观并发模型
5、快照:在事务在执行期间运行于快照隔离级别如果有进程读取数据,该进程将得到数据在事务开始时最后的一致性版本,他在事务开始时可用。从技术上讲,当执行事务中的第一条语句时认为事务已经开始。只要一个事务执行修改的同时至少还有一个事务运行于快照隔离级别下,sql server 就需要在修改之前存储行的一致性版本,不管这个修改事务是否运行在快照隔离级别下。当修改数据的事务开始后,处于快照隔离级别下的其他进程就有可能请求行的早期一致性版本。
特点:如果有进程读取数据,该进程将得到数据在事务开始时最后的一致性版本。另外,在读取数据的时候,不请求任何锁。
能够解决的并发冲突问题:脏读,不可重复读,丢失修改,幻读。
快照隔离级别还提供了更新冲突检测的能力:如果在你第一次读取数据以及尝试修改它之间有另外一个进程修改该数据,sql server将检测到这种更新冲突并中断事务。
6、已提交读快照:已提交读快照隔离级别有两点不同于快照隔离级别,第一个区别是读取器会获取数据在语句开始时而不是事务开始时的最新一致性版本。此外,该隔离级别不检测更新冲突。
能够解决的并发冲突问题:脏读
以上两种隔离级别是乐观控制模式
对于乐观控制模式:可以通过编程解决丢失修改的问题,对于不可重复读和幻想只能在数据库中解决。
产生幻像的一般原因:使用游标会产生。不是用游标一般不会出现不可重复读和幻象。