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 属性。
l 当启动交易时,使用 OLE DB 的应用程序可以将 isoLevel 设为所要的交易隔离等级,以呼叫 ITransactionLocal::StartTransaction。当在自动认可模式中指定隔离等级时,使用 OLE DB 的应用程序可以将 DBPROPSET_SESSION 属性 DBPROP_SESS_AUTOCOMMITISOLEVELS 设为所要的交易隔离等级。
l 使用 ODBC 的应用程序可以使用 SQLSetConnectAttr 来设定 SQL_COPT_SS_TXN_ISOLATION 属性。
4 悲观锁
悲观锁是指假设并发更新冲突会发生,所以不管冲突是否真的发生,都会使用锁机制。
悲观锁会完成以下功能:锁住读取的记录,防止其它事务读取和更新这些记录。其它事务会一直阻塞,直到这个事务结束。
悲观锁是在使用了数据库的事务隔离功能的基础上,独享占用的资源,以此保证读取数据一致性,避免修改丢失。
悲观锁可以使用Repeatable Read事务,它完全满足悲观锁的要求。
5 乐观锁
乐观锁不会锁住任何东西,也就是说,它不依赖数据库的事务机制,乐观锁完全是应用系统层面的东西。
如果使用乐观锁,那么数据库就必须加版本字段,否则就只能比较所有字段,但因为浮点类型不能比较,所以实际上没有版本字段是不可行的。
6 死锁
当二或多个工作各自具有某个资源的锁定,但其它工作尝试要锁定此资源,而造成工作永久封锁彼此时,会发生死锁。例如:
1. 事务 A 取得数据列 1 的共享锁定。
2. 事务B 取得数据列 2 的共享锁定。
3. 事务A 现在要求数据列 2 的独占锁定,但会被封锁直到事务B 完成并释出对数据列 2 的共享锁定为止。
4. 事务B 现在要求数据列 1 的独占锁定,但会被封锁直到事务A 完成并释出对数据列 1 的共享锁定为止。
等到事务B 完成后,事务A 才能完成,但事务B 被事务A 封锁了。这个状况也称为「循环相依性」(Cyclic Dependency)。事务A 相依于事务B,并且事务B 也因为相依于事务A 而封闭了这个循环。
例如以下操作就会产生死锁,两个连接互相阻塞对方的update。
连接1:
begin tran
select * from customers
update customers set CompanyName = CompanyName
waitfor delay '00:00:05'
select * from Employees
–因为Employees被连接2锁住了,所以这里会阻塞。
update Employees set LastName = LastName
commit tran
连接2:
begin tran
select * from Employees
update Employees set LastName = LastName
waitfor delay '00:00:05'
select * from customers
--因为customers被连接1锁住了,所以这里会阻塞。
update customers set CompanyName = CompanyName
commit tran
SQL Server遇到死锁时会自动杀死其中一个事务,而另一个事务会正常结束(提交或回滚)。
SQL Server对杀死的连接返回错误代码是1205,异常提示是:
Your transaction (process ID #52) was deadlocked on {lock | communication buffer | thRead} resources with another process and has been chosen as the deadlock victim. Rerun your transaction.
除了Read UnCommitted和Snapshot,其它类型的事务都可能产生死锁。
相关推荐
Oracle 数据库隔离级别是数据库事务处理中的核心概念,它决定了事务在并发环境下如何访问和处理数据,以确保数据的一致性和完整性。隔离级别主要解决的是并发操作中的脏读、不可重复读和幻读问题。 脏读(Dirty ...
数据库隔离级别是数据库管理系统中用于控制事务之间交互作用的一个关键特性,它旨在解决并发操作中可能出现的数据不一致性和并发问题。在数据库系统中,主要有四种隔离级别,分别是Read Uncommitted、Read Committed...
MySQL数据库隔离级别
数据库隔离级别的选择与实现
数据库隔离级别与脏读、幻读的深入解析
事务隔离级别 课程目标 了解 —— 事务隔离级别的概念; 理解 —— 事务隔离的四种级别; 掌握 —— 事务隔离级别的设置; 事务隔离级别 事务隔离:每一个事务都有一个所谓的隔离级,它定义了用户彼此之间隔离和交互...
总的来说,数据库隔离级别的选择是一个权衡过程,需要在数据一致性、并发性和性能之间找到合适的平衡点。在设计数据库系统和应用程序时,理解这些隔离级别及其可能产生的效果至关重要,以便做出最佳决策。
数据库事务和隔离级别
近突然发现忘了数据库锁和数据库隔离级别,时常弄混它们之间的关系。为此特此写下此博客,以方便自己复习,同时也可以帮助博友。 数据库锁 数据库锁是事务T在对某个数据对象(例如表、记录等)操作之前,先向...
数据库隔离级别是数据库管理系统在并发环境下确保事务一致性和数据完整性的关键设置。Spring框架与MySQL数据库结合使用时,可以通过配置事务管理器来控制事务的隔离级别,以达到优化性能和保证数据一致性。以下是对...
GBase 8s 是一款高性能的关系型数据库管理系统,它提供了多种隔离级别来处理并发事务,以确保数据的一致性和完整性。隔离级别是数据库系统解决并发控制的重要机制,它定义了事务在执行过程中如何与其他事务交互,...
介绍数据库事务的四种隔离级别,比较不同隔离级别的区别和影响
GBase8s_隔离级别.docx
数据库系统提供了不同的隔离级别来控制这种影响: - **未提交读(Read Uncommitted)**:最低的隔离级别,允许读取未提交的数据,可能导致脏读、不可重复读和幻读。 - **提交读(Read Committed)**:在提交后才...
查询:默认事务隔离级别 mysql> select @@tx_isolation;当前会话的默认事务隔离级别 mysql> select @@session.tx_isolation;当前会话的默认事务隔离级别 mysql> select @@global.tx_isolation;全局的事务隔离级别