小议数据库系统中的并发控制
来源:互联网 发布:好听的淘宝男装店名 编辑:程序博客网 时间:2024/04/30 08:18
在一般的数据库系统中,对于事务的并发处理一般是遵循二级封锁协议。而二级封锁协议是在一级封锁协议之上定制的。
一级封锁协议的要求是:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。一级封锁协议可以防止丢失修改,并保证事务T是可恢复的。在一级封锁协议中,如果仅仅是读数据而不进行修改是不加锁的,所以它不能保证可重复读和不读“脏”数据
二级封锁协议是在一级封锁协议的基础上加上在读取数据R之前必须先对其价S锁,读完即可释放,注意读完就释放,这样其实还是不能做到可重复读的。举个例子:注意HOLDLOCK,它要求事务一直保持IS和S锁直到事务结束,这样默认的二级封锁协议被扩展成三级了
此时:
一级封锁协议的要求是:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。一级封锁协议可以防止丢失修改,并保证事务T是可恢复的。在一级封锁协议中,如果仅仅是读数据而不进行修改是不加锁的,所以它不能保证可重复读和不读“脏”数据
二级封锁协议是在一级封锁协议的基础上加上在读取数据R之前必须先对其价S锁,读完即可释放,注意读完就释放,这样其实还是不能做到可重复读的。举个例子:
BEGIN TRANSACTION T1
--加S锁
SELECT * FROM CUSTOMERS
--释放S锁
--加S锁
SELECT * FROM CUSTOMERS
--释放S锁
如果此时另一个并发事务更新了CUSTOMERS表,那么事务T1再次读表的话数据就会不一致,这就是不可重复读。
但是二级封锁协议防止出现丢失修改和读脏数据的情况。
下面说一下三级封锁协议
三级封锁协议是一级封锁协议的基础上加上读取数据R前必须对其加S锁并且到事务结束再释放。这样就可重复读了
BEGIN TRANSACTION T1
--加S锁
SELECT * FROM CUSTOMERS HOLDLOCK
--不释放S锁
--此时如果有一个并发事务进行更新操作,因为无法获得x锁将会被挂起直到事务结束。
COMMIT TRANSACTION T1
--释放S锁
--加S锁
SELECT * FROM CUSTOMERS HOLDLOCK
--不释放S锁
--此时如果有一个并发事务进行更新操作,因为无法获得x锁将会被挂起直到事务结束。
COMMIT TRANSACTION T1
--释放S锁
在很多DBMS中例如SQL SERVER默认在事务中使用的二级封锁协议
即:
任何更新和插入操作都会在对象上加IX锁,在更新和插入的元组上加X锁,直到事务结束(因为这些操作已经影响了数据库的内容,而且有可能回滚)。所以任何其他并发事务虽然可以在此对象上加IS或IX锁,但是对应的S或X锁只能加在未加X锁的元组上。否则将会被挂起
从对象内读取某些元组,在读取时会在对象上加IS锁,在所读取的元组上加S锁,但是一旦读取结束便会释放掉。显然这样是不可重复读的,当然为了避免不可重复读,我们可以在语句后加一个 HOLDLOCK 这样可以使IS和S锁保持到事务结束,这样就可重复读了,如果这样那么默认的二级封锁协议就被我们扩展成三级封锁协议了。例如:
BEGIN TRANSACTION T1 --开始一个事务
SELECT * FROM CUSTOMERS --从对象内选择某些元组,在选择时会加IS和S锁
--读取结束便会释放掉IS和S锁
BEGIN TRANSACTION T2
UPDATE CUSTOMERS SET COMPANY = 'AAA' WHERE CUST_NUM = 2101 --这个事务是可以执行的,因为现在不存在任何锁
--在TI中再执行
UPDATE CUSTOMERS SET COMPANY = 'BBB' WHERE CUST_NUM = 2101
--这个操作将被挂起,因为T2已经在对象上加了IX锁,虽然T1需要的IX锁可以成功加在表上,但是因为它欲加在元组2101上的X锁与T2中已存在的X锁是不兼容的(在同一元组上),所以会被挂起。
SELECT * FROM CUSTOMERS --从对象内选择某些元组,在选择时会加IS和S锁
--读取结束便会释放掉IS和S锁
BEGIN TRANSACTION T2
UPDATE CUSTOMERS SET COMPANY = 'AAA' WHERE CUST_NUM = 2101 --这个事务是可以执行的,因为现在不存在任何锁
--在TI中再执行
UPDATE CUSTOMERS SET COMPANY = 'BBB' WHERE CUST_NUM = 2101
--这个操作将被挂起,因为T2已经在对象上加了IX锁,虽然T1需要的IX锁可以成功加在表上,但是因为它欲加在元组2101上的X锁与T2中已存在的X锁是不兼容的(在同一元组上),所以会被挂起。
如果是这样呢?
UPDATE CUSTOMERS SET COMPANY = 'BBB' WHERE CUST_NUM = 2102
这是可以执行的,因为它需要加X锁在2102这个元组上,这个元组并没有被别的事务加锁
OK,假设我们一开始是这样执行的,那会怎样呢
BEGIN TRANSACTION T1 --开始一个事务
SELECT * FROM CUSTOMERS HOLDLOCK--从对象内选择某些元组,在选择时会加IS和S锁
--IS和S锁不会被释放直到事务结束为止
SELECT * FROM CUSTOMERS HOLDLOCK--从对象内选择某些元组,在选择时会加IS和S锁
--IS和S锁不会被释放直到事务结束为止
此时:
BEGIN TRANSACTION T2
UPDATE CUSTOMERS SET COMPANY = 'AAA' WHERE CUST_NUM = 2101
--这个操作会被挂起,因为T1已经在所有的元组上加了S锁,并且T1现在并没有提交或者回滚。
UPDATE CUSTOMERS SET COMPANY = 'AAA' WHERE CUST_NUM = 2101
--这个操作会被挂起,因为T1已经在所有的元组上加了S锁,并且T1现在并没有提交或者回滚。
以上只是简单地讨论了DBMS中的并发处理,如果有什么问题还希望大家指正,本文欢迎转载但是请注明出处
blog.csdn.net/lesky
- 小议数据库系统中的并发控制
- 小议数据库系统中的并发控制
- 数据库中的并发控制
- 【数据库系统概论】-并发控制
- 数据库系统概论-011: 并发控制
- 数据库系统原理教程 第八章 数据库并发控制
- 第11章 并发控制(数据库系统概论)
- 数据库系统实现_第九章 并发控制
- 第04章 数据库系统 之 并发控制
- 控制数据库的并发
- 数据库并发控制技术
- 数据库并发控制技术
- 数据库并发控制技术
- 数据库并发控制
- 数据库并发控制技术
- 数据库 并发控制 笔记
- 数据库并发控制技术
- 数据库并发控制技术
- [转载]LCC编译器的源程序分析(17)参数变量的声明
- [转载]LCC编译器的源程序分析(18)函数定义
- [转载]LCC编译器的源程序分析(19)全局函数的定义
- linux进程之fork vs vfork
- [转载] LCC编译器的源程序分析(20)复合语句
- 小议数据库系统中的并发控制
- javascript execCommand指令集
- gvim for windows 设置
- 用JavaScript实现超酷的“网页时钟”
- delphi读取mysql中编码为GBK的表时乱码的消除
- 广告
- 用正则表达式限制文本框只能输入数字,小数点,英文字母,汉字等各类代码
- The C Programming Language 2nd Edition Execise4-2 Answer
- 查看sqlserver2000的版本select写