Oracle事务与锁
2017-12-13
1 数据库事务概括
1.1 事务定义
1.2 事务生命周期
1.3 事物的特性
1.4 死锁
2 事务相关语句
2.1 事务相关语句概括
2.2 建立事务隔离级别
3 锁
3.1 锁模式
3.2 乐观锁和悲观锁
参考
1 数据库事务概括
1.1 事务定义
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
1.2 事务生命周期
事务的开始和结束
开始事务:连接到数据库,执行DML、DCL、DDL语句
结束事务: 1. 执行DDL(例如CREATE TABLE),DCL(例如GRANT),系统自动执行COMMIT语句
2. 执行COMMIT/ROLLBACK
3. 退出/断开数据库的连接自动执行COMMIT语句
4. 进程意外终止,事务自动rollback
5. 事务COMMIT时会生成一个唯一的系统变化号(SCN)保存到事务表
事务的提交和回滚:COMMIT/ROLLBACK
保存点(savepoint): 可以在事务的任何地方设置保存点,以便ROLLBACK
1.3 事物的特性
事务所应该具有的四个特性:
- 原子性(Atomicity):原子性意味着数据库中的事务执行是作为原子。即不可再分,整个语句要么执行,要么不执行。
- 每一条T-SQL语句都可以看作是默认被包裹在一个事务之中的,SQL Server对于每一条单独的语句都实现了原子性。
- 如果用户想要自己定义原子的大小,则需要包含在事务中来构成用户自定义的原子粒度。
事务实现的自定义原子性往往是和业务相关的,比如银行转账,从A账户减去100,在B账户增加100,如果这两个语句不能保证原子性的话,比如从A账户减去100后,服务器断电,而在B账户中却没有增加100。作为客户可不希望这种情况。
- 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
一致性分为两个层面: - 数据库机制层面
数据库层面的一致性是,在一个事务执行之前和之后,数据会符合你设置的约束(唯一约束,外键约束,Check约束等)和触发器设置.这一点是由数据库进行保证的. - 业务层面
对于业务层面来说,一致性是保持业务的一致性。这个业务一致性需要由开发人员进行保证。很多业务方面的一致性可以通过转移到数据库机制层面进行保证.比如,产品只有两个型号,则可以转移到使用CHECK约束使某一列必须只能存这两个型号。
- 隔离性(Isolation):隔离性。事务的执行是互不干扰的,一个事务不可能看到其他事务运行时,中间某一时刻的数据。
事务之间的互相影响的情况分为4种: - 脏读:某个事务读取的数据是另一个事务正在处理的数据。而另一个事务可能会回滚,造成第一个事务读取的数据是错误的。
- 不可重复读:在一个事务里两次读入数据,但另一个事务已经更改了第一个事务涉及到的数据,造成第一个事务读入旧数据。
- 幻读:幻读是指当事务不是独立执行时发生的一种现象。例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
- 更新丢失:多个事务同时读取某一数据,一个事务成功处理好了数据,被另一个事务写回原值,造成第一个事务更新丢失。
- 持久性(Durability):意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
即使出现了任何事故比如断电等,事务一旦提交,则持久化保存在数据库中.
1.4 死锁
当两个事务相互等待对方释放资源时,就会形成死锁
2 事务相关语句
2.1 事务相关语句概括
SET TRANSACTION --设置事务属性 SET CONSTRAINT --设置约束 SAVEPOINT --建立存储点 RELEASE SAVEPOINT --释放存储点 ROLLBACK --回滚 COMMIT --提交
2.2 建立事务隔离级别
SET TRANSACTION READ ONLY --事务中不能有任何修改数据库中数据的操作语句,这包括 insert、update、delete、create语句 SET TRANSACTION READ WRITE --默认设置,该选项表示在事务中可以有访问语句、修改语句 -- oracle支持的隔离级别:(不支持脏读) SET TRANSACTION ISOLATION LEVEL READ COMMITTED --不允许脏读,允许幻想读和不可重复读 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE --以上三种都不允许 serialzable可以执行DML操作 -- sql标准还支持READ UNCOMMITTED (三种都允许)和 REPEATABLE READ(不允许不可重复读和脏读,只允许幻想读)
注意:这些语句是互斥的,不能够同时设置两个或者两个以上的选项
3 锁
事务隔离级别是并发控制的整体解决方案,其实际上是综合利用各种类型的锁和行版本控制,来解决并发问题。
3.1 锁模式
两种模式锁:排他锁(X锁)和共享锁(S锁):
- 排他锁也叫写锁.这种模式的锁防止资源的共享,用做数据的修改。
假如有事务T给数据A加上该锁,那么其他的事务将不能对A加任何的锁,所以此时只允许T对该数据进行读取和修改,直到事务完成将该类型的锁释放为止。 - 共享锁也可以叫读锁.该模式锁下的数据只能被读到,不能被修改。
如果有事务T给数据A加上共享锁后,那么其他事务不能对其加排他锁,只能加共享锁.加了该锁的数据可以被并发地读取.锁是实现并发的主要手段,很多都是由数据库自动管理,当事务提交后会自动释放锁。
再细分:
- RS(行级共享锁,ROW SHARE):该模式下不允许其他的并行会话对同一张表使用排它锁,但允许其利用DML语名或Lock命令锁定同一张表中的其他记录.select ...from for update语名就是给记录加上了RS锁.
- RX(行级排他锁,ROW EXCLUSIVE):该模式下允许并行会话对同一张表的其他数据进行修改,但不允许并行会话对同一张表使用排他锁.
- S(共享锁,SHARE):该模式下,不允许会话更新表,但允许对表添加RS锁.
- SRX(共享行级排他锁,SHARE ROW EXCLUSIVE):该模式下,不能对同一张表进行DML操作,也不能添加S锁.
- X(排他锁,EXCLUSIVE):该模式下,其他的并行会话不能对表DML和DDL操作,该表只能读.
表1、oracle表级锁5种模式的兼容性
表2、oracle中各种语句锁产生的表级锁模式
3.2 乐观锁和悲观锁
乐观锁
- 乐观锁不会锁住任何东西,也就是说,它不依赖数据库的事务机制,乐观锁完全是应用系统层面的东西。
- 如果使用乐观锁,那么数据库就必须加版本字段,否则就只能比较所有字段,但因为浮点类型不能比较,所以实际上没有版本字段是不可行的。
悲观锁
- 悲观锁是指假设并发更新冲突会发生,所以不管冲突是否真的发生,都会使用锁机制。
- 悲观锁会完成以下功能:锁住读取的记录,防止其它事务读取和更新这些记录。其它事务会一直阻塞,直到这个事务结束。
- 悲观锁是在使用了数据库的事务隔离功能的基础上,独享占用的资源,以此保证读取数据一致性,避免修改丢失。
- 悲观锁可以使用Repeatable Read事务,它完全满足悲观锁的要求。
参考
[1] oracle事务和锁
[2] 悲观锁和乐观锁
[4] oracle查看被锁的表和解锁
[6] Oracle锁表查询和解锁方法