并发控制
1. 并发冲突
当两个进程试图在同一时间修改同一数据,就会产生冲突。
2. 并发控制
有两种方式管理并发数据访问:乐观并发控制、悲观并发控制。
这两种控制模式的区别在于,是在冲突发生前进行防止,还是在发生后采用某种方法来处理冲突。
3. 悲观并发控制
悲观并发模式假定系统中存在足够多的数据修改操作,以致任何确定的读操作都可能会受到由别的用户所制造的数据修改的影响。
也就是说,悲观并发模式假定冲突总是会发生的。
悲观并发控制是通过独占正在被读取的数据来避免冲突。
但是独占数据会导致其它进程无法修改该数据,进而产生阻塞——读数据和写数据会互相阻塞。
4. 乐观并发控制
乐观并发模式假定系统的数据修改操作只会生产非常少的冲突,也就是说任何进程都不太可能修改别的进程正在访问的数据。
乐观并发模式下,读数据和写数据之间不会发生冲突,只有写数据与写数据之间会发生冲突。即读数据不会产生阻塞,只有写数据才会产生阻塞。
5. 并发冲突生产的问题
5.1. 丢失更新(Lost updates)
两个进程同时读取一笔数据,然后进行修改,那么后提交的数据会覆盖先提交的数据。
如果数据允许覆盖式更新(比如用户姓名),那么丢失更新并不算太大的问题,如果数据是累加式更新(比如库存数量),那么丢失更新是非常严重的问题,并且在非并发模式下无法重复问题的发生。
5.2. 脏读(Dirty reads)
当一个进程更新了数据,但(事务)未提交,这时候另一个进程读取同一笔数据,如果前一个进程取消了更新(事务回滚),那么后一个进程读取的就是脏数据。
脏读会产生严重的问题,在任何情况下都是不允许的。
5.3. 不可重复读(Non-repeatable reads)
当一个进程读取了一笔数据后,另一个进程更新了同一笔数据,然后第一个进程再次读取同一笔数据,却得到了与第一次读取不同的结果。
在事务A更新记录之后(update Customers set Name = 'B' where Name = 'A'),事务B读取相同记录(select Name form Customers where Name = 'A'),但事务B拿到的是事务A更新之后的数据(Customers.Name的值为'B'),在事务B读取记录之后,事务A进行了事务回滚(Customers.Name的值为'A'),导致事务B的数据是不真实的。
5.4. 幻读(Phantoms)
幻读与脏读的相似之处在于:两者都是两次读取的结果不一致。
不同之处在于:幻读是两次读取的记录数量不一致,而脏读是两次读取的记录的数据不一致。
事务A读取记录之后(select * from Customers where Name like 'A%'),事务B又插入了符合事务A读取条件的新记录(insert into Customers(Name) values('AAA')),那么当事务A再用相同条件读取记录时,得到的集合却与上一次读取不同(多了记录)。
6. 隔离级别
SQL Server2005支持5种隔离级别来控制冲突。其中三种只在悲观并发模式中使用,一种只在乐观并发模式中使用,另一个可以在两种模式中使用。
6.1. 未提交读(Uncommitted Read)
未提交读只能防止“丢失更新”问题,其它问题不能防止。
未提交读是针对阻塞太频繁的悲观并发控制,因为它只是忽略了锁,而不保障事务的一致性。
6.2. 已提交读(Read Committed)
已提交读既可以是乐观的也可以是悲观的,这取决于数据 库的read_committed_snapshot设置。默认情况下这个选项是关闭的,所以该隔离级别默认情况下是采用悲观并发控制。
已提交读可以防止脏读问题。
6.3. 可重复读(Repeatable Read)
可重复读是一种悲观的隔离级别。它在已提交读的基础上增加了新特性:确保当事务重新访问数据或查询被再一次执行时,数据将不会再发生改变。
可重复读不但可以防止脏读问题,还可以防止不可重复读问题,但是不能防止幻读问题。
注意,可重复读的资源开销是很大的,事务中所有的数据必须等待事务完成之后才能访问。
6.4. 快照(Snapshot)
快照是一种乐观隔离级别。
Snapshot事务中任何语句所读取的记录,都是事务启动时的数据。
这相当于事务启动时,数据库为事务生成了一份专用“快照”。
在当前事务中看到不其它事务在当前事务启动之后所进行的数据修改。
Snapshot事务不会读取记录时要求锁定,读取记录的Snapshot事务不会锁住其它事务写入记录,写入记录的事务也不会锁住Snapshot事务读取数据。
快照隔离级别的事务不是串行执行的,两个进程同时使用快照隔离,如果它们执行多次,可能最终产生的结果不会一致。(这段话要证实)
6.5. 可串行化(Serializable)
可串行化是一种悲观隔离级别。它在可重复读的基础上增加了新的特性:确保在两次查询的中间,不会增加新的行。
可串行化是最健壮的悲观隔离级别,因为它防止了并发冲突产生的4个问题。
可串行化也是资源开销最大的措施。当使用可串行化隔离时,如果SQL的条件字段没有索引,那么SQL Server会产生表级锁。
6.6. 总结
模式 |
脏读 Dirty Read |
不可重复读 Non-Repeatable Read |
幻读 Phantom Read |
并发控制模式 |
未提交读 READ UNCOMMITTED |
会 |
会 |
会 |
悲观 |
可提交读 READ COMMITTED (默认选项) |
不会 |
会 |
会 |
悲观 |
可提交读 READ COMMITTED(Snapshot选项) |
不会 |
会 |
会 |
乐观 |
可重复读 REPEATABLE READ |
不会 |
不会 |
会 |
悲观 |
快照 SNAPSHOT |
不会 |
不会 |
不会 |
乐观 |
可串行化 SERIALIZABLE |
不会 |
不会 |
不会 |
悲观 |
7. 锁
7.1. 死锁
当二或多个工作各自具有某个资源的锁定,但其它工作尝试要锁定此资源,而造成工作永久封锁彼此时,会发生死锁。例如:
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,其它类型的事务都可能产生死锁。
7.2. 悲观锁
悲观锁是指假设并发更新冲突会发生,所以不管冲突是否真的发生,都会使用锁机制。
悲观锁会完成以下功能:锁住读取的记录,防止其它事务读取和更新这些记录。其它事务会一直阻塞,直到这个事务结束。
悲观锁是在使用了数据库的事务隔离功能的基础上,独享占用的资源,以此保证读取数据一致性,避免修改丢失。
悲观锁可以使用Repeatable Read事务,它完全满足悲观锁的要求。
7.3. 乐观锁
乐观锁不会锁住任何东西,也就是说,它不依赖数据库的事务机制,乐观锁完全是应用系统层面的东西。
如果使用乐观锁,那么数据库就必须加版本字段,否则就只能比较所有字段,但因为浮点类型不能比较,所以实际上没有版本字段是不可行的。
7.4. 悲观离线锁
悲观离线锁是应用程序级别的机制,它是由应用程序实现的,不是数据库实现的。
相关推荐
数据库并发控制是数据库管理系统中的关键组成部分,特别是在多用户系统中,确保数据的一致性和完整性至关重要。并发控制的主要目的是防止多个事务在访问共享资源时产生不正确的数据状态,从而避免诸如丢失更新、脏读...
分布式数据库并发控制是数据库系统中的一个重要领域,尤其在多处理器或多节点环境中,多个事务可能同时对数据库进行操作,这就会引入一系列并发问题。并发执行在单处理器和多处理器环境下都有可能发生,不同的是,在...
### 数据库并发控制的基本方法 #### 一、并发控制概览 在数据库系统中,**并发控制**是一项关键的技术,用于确保多个事务能够同时访问数据而不引起数据不一致的问题。并发控制的目标是使得多个事务的并发执行看...
在数据库管理系统中,并发控制是确保多用户环境下数据一致性与完整性的关键机制。DB2和Oracle都是广泛应用的关系型数据库,它们都采用了锁作为主要的并发控制手段。本文将对比分析DB2和Oracle的并发控制,特别是锁的...
数据库思维导图——并发控制 并发控制 多事务执行方式 (1)事务串行执行 每个时刻只有一个事务运行,其他事务必须等到这个事务结束以后方能运行 不能充分利用系统资源,发挥数据库共享资源的特点 (2)交叉并发方式...
并发控制概论 本章节主要讨论数据库系统中的并发控制技术,旨在解决多用户数据库系统中并发事务执行带来的问题。数据库管理系统必须提供并发控制机制,以确保事务的隔离性和数据库的一致性。 11.1 并发控制概述 ...
### 数据库并发控制及其在SQL Server 2000中的应用 #### 一、并发控制概述 在现代数据库管理系统(DBMS)中,**并发控制**是一项关键的技术,尤其是在多用户环境中,它确保了多个事务能够同时访问数据库而不会导致...
事务和并发控制是数据库管理中的核心概念,特别是在使用ORM框架如Hibernate时,理解它们的工作原理至关重要。本文将深入探讨Hibernate中的事务管理和并发控制。 首先,事务是数据库操作的基本单位,它保证了数据的...
并发控制是数据库管理系统中至关重要的一个方面,它确保在多用户环境下,多个事务可以同时进行而不会破坏数据的完整性。并发控制的主要目标是避免事务之间的冲突,防止出现诸如脏读、不可重复读和幻读等问题。 脏读...
锁的运用是并发控制的核心,它能够在多用户环境中协调不同事务的操作,防止数据冲突和异常状态的出现,如脏读、不可重复读和幻觉读。 ### 并发控制的重要性 在现代数据库系统中,尤其是像Oracle这样的大型关系型...
### 并发控制实现方法的比较研究 #### 引言 数据库管理系统(DBMS)的核心功能之一就是并发控制,它不仅确保了数据的一致性和正确性,还极大地影响着整个系统的性能表现。随着互联网技术的发展,数据库系统面临...
数据库并发控制PPT学习教案 数据库并发控制是数据库管理系统(DBMS)中一个非常重要的概念。它是指在多个事务同时访问数据库时,如何确保事务之间的一致性和隔离性,防止数据不一致和丢失。 在数据库并发控制中,...
分布式事务并发控制是分布式系统中确保多个参与节点间事务一致性的关键技术。在分布式系统中,事务可能需要同时在多个服务器上执行,这就要求系统能够在这些服务器之间进行协调,以保证事务的ACID属性(原子性、一致...
在数据库管理中,事务管理是至关重要的一个环节,它涵盖了并发控制和恢复机制,确保数据在多用户同时访问时的完整性和一致性。本章主要讨论的是如何在数据库系统中实现有效的事务管理和处理并发操作的问题。 首先,...
分布式数据库系统的并发控制方法是现代信息技术领域中的一个重要研究方向,主要目标是保证在分布式环境下多个用户或进程同时访问数据库时的正确性和一致性。本文详细探讨了这一领域的理论基础和技术实践。 首先,...
数据库并发控制是数据库管理系统中的关键组成部分,其目的是确保在多用户环境下,多个事务同时执行时,数据的完整性和一致性不受影响。并发控制的主要任务是防止事务间的不正确交互,如脏读、不可重复读和幻读等现象...
"数据库原理与设计课件:第9章 并发控制" 本节课主要讲解数据库系统中的并发控制理论和技术。并发控制是数据库系统中的一种机制,用于确保多个事务并发执行时的正确性和一致性。 首先,数据库系统具有多用户特征,...
数据库并发控制是数据库管理系统中确保多用户环境下的数据一致性、避免数据不一致的重要技术。在数据库第四版答案(王珊萨师煊)第11章并发控制中,主要讨论了并发控制的原因、并发操作可能产生的问题及解决方案,以及...
然而,分布式数据库系统的并发控制成为了系统性能优劣的决定性因素。 并发控制的核心问题是,当多个用户或进程同时对数据库进行读写操作时,如何确保数据的完整性和一致性。若处理不当,就可能出现数据丢失、读脏...