- 爱易网页
-
数据库教程
- 悲观锁跟乐观锁
日期:2014-05-16 浏览次数:20536 次
悲观锁和乐观锁
1 事务隔离
事务隔离是数据库提供的功能。
SQL Server通过SET TRANSACTION ISOLATION LEVEL语句设置事务隔离级别:
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SNAPSHOT
| SERIALIZABLE
}
[ ; ]
Read Committed是SQL Server的预设隔离等级。
1.1 READ UNCOMMITTED
Read UnCommitted事务可以读取事务已修改,但未提交的的记录。
Read UnCommitted事务会产生脏读(Dirty Read)。
Read UnCommitted事务与select语句加nolock的效果一样,它是所有隔离级别中限制最少的。
1.2 READ COMMITTED
Read Committed事务不能读取事务已修改,但未提交的记录。
Read Committed是SQL Server的预设隔离等级。
1.3 REPEATABLE READ
Repeatable Read事务不能读取交易已修改,但未提交的记录,并且在事务完成之前,任何其它事务都不能修改目前事务已读取的记录。
其它事务仍可以插入新记录,但必须符合当前事务的搜索条件——这意味着当前事务重新查询记录时,会产生幻读(Phantom Read)。
1.4 SNAPSHOT
Snapshot事务中任何语句所读取的记录,都是事务启动时的数据。
这相当于事务启动时,数据库为事务生成了一份专用“快照”。
在当前事务中看到不其它事务在当前事务启动之后所进行的数据修改。
Snapshot事务不会读取记录时要求锁定,读取记录的Snapshot事务不会锁住其它事务写入记录,写入记录的事务也不会锁住Snapshot事务读取数据。
1.5 SERIALIZABLE
Serializable事务会产生以下效果:
1.语句无法读取其它事务已修改但未提交的记录。
2.在当前事务完成之前,其它事务不能修改目前事务已读取的记录。
3.在当前事务完成之前,其它事务所插入的新记录,其索引键值不能在当前事务的任何语句所读取的索引键范围中。
Serializable事务与select语句加holdlock的效果一样。
2 READ COMMITTED 和 REPEATABLE READ
Read Committed 和 Repeatable Read 是最常用的两种事务。
Read Committed 是 SQL Server的默认级别;而 Repeatable Read 比Read Committed 更能保证数据一致性。
2.1 特点
Read Committed会阻塞其它事务中的update,但不会阻塞select。
Repeatable Read不但会阻塞其它事务中的update,还会阻塞select。
Read Committed 和 Repeatable Read 的相同点是:都会阻塞其它事务的update语句。
Read Committed 和 Repeatable Read 的不同点是:Read Committed 不会阻塞其它事务的select语句,但Repeatable Read阻塞。
注意,Read Committed 和 Repeatable Read 都是行级锁,它们只会锁住与自己相关的记录。当事务提交之后,阻塞的语句就会继续执行。
2.2 理解
2.2.1 READ COMMITTED
Read Committed 事务的含义是我select出来的记录,别人只能看,不能改(只阻塞别的事务的update)。
Read Committed 的缺点是:无法防止读取不一致和修改丢失。
读取不一致是因为Read Committed 不锁住读取的记录;修改丢失是因为别的事务也能读取当前事务的记录,虽然会阻塞别的事务的update,但在当前事务提交之后,别的事务的update语句会继续执行,进而覆盖上一次事务的结果,导致上一次的修改丢失。
2.2.2 REPEATABLE READ
Repeatable Read 事务的含义是我select出来的记录,不允许别人看,也不允许别人改(阻塞别的事务select、update),这就意味着我可以在事务中多次select数据,而不用担心出现“脏读”——这就是“可重复读取”的意思。
Repeatable Read 虽然解决了Read Committed 事务的读取不一致和修改丢失的缺点,但它也有缺点(尽管这个缺点Read Committed 也有):
Repeatable Read 不会阻塞insert和delete,所以会出现“幻读”—— 两次select的结果不一样。还有,Repeatable Read 占用的资源比Read Committed 大。
3 在应用程序中设置事务隔离级别
READ COMMITTED 是 Microsoft SQL Server Database Engine 的预设隔离等级。
已指定隔离等级时,在 SQL Server 工作阶段中,所有查询和数据操作语言 (DML) 陈述式的锁定行为都会在此隔离等级运作。此隔离等级会维持有效,直到工作阶段结束或隔离等级设为另一个等级为止。
如果应用程序必须在不同隔离等级操作,可以使用下列方法来设定隔离等级:
l 执行 SET TRANSACTION ISOLATION LEVEL Transact-SQL 陈述式。
l 如果 ADO.NET 应用程序使用 System.Data.SqlClient 管理的命名空间,可以使用 SqlConnection.BeginTransaction 方法来指定 IsolationLevel 选项。
l 使用 ADO 的应用程序可以设定 Autocommit Isolation Levels 属性。