目录
数据库事务是指作为单个逻辑工作单元的一系列操作的集合。一个典型的事务由应用程 序中的一组操作序列组成,对于 DM 数据库来说,第一次执行 SQL 语句时,隐式地启动一个 事务,以 COMMIT 或 ROLLBACK 语句/方法显式地结束事务。另外,在执行 DDL 前,DM 数据库会自动把前面的操作进行提交,DDL 前面的操作作为一个完整的事务结束,DDL 语句 本身所属事务则根据“DDL_AUTO_COMMIT”配置参数决定是否隐式地提交。(ALTER TABLESPACE 和 ALTER USER 操作总是自动提交的)
查看DDL_AUTO_COMMIT参数值,默认DDL自动提交,只读参数,手工修改dm.ini重启数据库生效
select PARA_NAME,PARA_VALUE,PARA_TYPE,DESCRIPTION from v$dm_ini where para_name='DDL_AUTO_COMMIT';
修改后DM服务查看器重启数据库服务(或使用命令重启)
修改后查看:
COMMIT 操作会将该语句所对应事务对数据库的所有更新持久化(即写入磁盘),数据库此时进入一个新的一致性状态,同时该事务成功地结束。
ROLLBACK 操作将该语句所对应 事务对数据库的所有更新全部撤销,把数据库恢复到该事务初启动前的一致性状态。
SAVEPOINT
保存点提供了一种灵活的回滚,事务在执行中可以回滚到某个保存点,在该保存点以前的操作有效,而以后的操作被回滚掉。
--创建保存点:
SAVEPOINT sp_name;
--使用保存点,回滚到保存点
ROLLBACK TO SAVEPOINT sp_name;
-
事务特性
原子性
性保证事务包含的一组更新操作是原子不可分的,也就是说这些更新操作是 一个整体,对数据库而言全做或者全不做,不能部分地完成。
一致性
一致性要求事务执行完成后,将数据库从一个一致状态转变到另一个一致状态。
隔离性
某个并发事务所做的修改必须与任何其他的并发事务所做的修改相互隔离。
持久性
指一个事务一旦被提交,它对数据库中数据的改变就是永久性的。
-
事务提交
是提交事务对数据库所做的修改,将从事务开始的所有更新保存到数据库中,任何更改的记录都被写入日志文件并最终写入到数据文件;释放由事 务占用的资源,如锁。
修改了数据的事务被提交之前,DM数据库进行的操作:
a、生成回滚记录,包含了事务中各SQL语句所修改的数据的原始值
b、在系统的重做日志缓冲区生成重做日志记录,包含了对数据页和回滚页所进行的修改,这些记录可能在事务提交之前被写入磁盘;
c、对数据的修改已经被写入数据缓冲区,这些修改也可能在事务提交之前被写入磁盘。
事务commit之后,DM数据库的操作
a、 将事务任何更改的记录写入日志文件并最终写入到数据文件
b、释放事务上的所有锁,将事务标记为完成
c、返回提交成功消息给请求者
事务模式
(1)自动提交模式:
除了命令行交互式工具 DISQL 外,DM 数据库缺省都采用自动提交模式。
--设置当前会话为自动提交模式
SET AUTOCOMMIT ON;
(2)手动提交模式:
DM 数据库用户或者应用开发人员明确定义事务的开始和结束,这 些事务也被称为显式事务。
需手动执行COMMIT 提交 或者ROLLBACK 回滚 事务
(3)隐式提交模式:
在手动提交模式下,当遇到 DDL 语句时,DM 数据库会自动提交前面的事务,然后开始 一个新的事务执行 DDL 语句。
CREATE; ALTER; TRUNCATE; DROP; GRANT;REVOKE;审计设置语句
-
事务回滚
撤消该事务所做的任何更改。
回滚的两种形式:DM 数据库自动回滚,或者通过程序/ROLLBACK 命令手动回滚。
1、自动回滚:
若事务运行期间出现连接断开,DM 数据库都会自动回滚该连接所产生的事务。回滚会 撤消事务执行的所有数据库更改,并释放此事务使用的所有数据库资源。DM 数据库在恢复 时也会使用自动回滚。例如在运行事务时服务器突然断电,接着系统重新启动,DM 数据库 就会在重启时执行自动恢复。自动恢复要从事务重做日志中读取信息以重新执行没有写入磁 盘的已提交事务,或者回滚断电时还没有来得及提交的事务。
2、回滚到保存点:
将事务回滚到某个保存点的过程如下:
a、只回滚保存点之后的语句;
b、保留该保存点,其后创建的保存点都被清除;
c、释放此保存点之后获得的所有锁,保留该保存点之前的锁。
被部分回滚的事务依然处于活动状态,可以继续执行,一个事务结束后,保存点也都被清除
--设置第一个保存点,并插入一笔数据不提交
SAVEPOINT sp_01;
insert into DMHR.TEST01 VALUES(2,'test_sp01');
--设置第二个保存点,并插入一笔数据不提交
savepoint sp_02;
insert into DMHR.TEST01 VALUES(3,'test_sp02');
--设置第三个保存点,并插入一笔数据不提交
savepoint sp_03;
insert into DMHR.TEST01 VALUES(4,'test_sp03');
--回滚至第二个保存点,sp_03也会被清除
ROLLBACK TO SAVEPOINT SP_02;
insert into DMHR.TEST01 VALUES(3,'test_sp02');
commit;
开始前表数据:
设置三个保存点:
回滚后依然可继续执行:
commit结束事务,查看数据
3、语句级回滚:
如果在一个 SQL 语句执行过程中发生了错误,此语句对数据库产生的影响将被回滚, 回滚后就如同此语句从未执行过,这种操作被称为语句级回滚。不会影响此语句之前所做的数据修改。
当 INI 参数 ROLL_ON_ERR 为缺省值 0 时,在 SQL 语句执行过程中发生的错误,将会 导致语句级回滚,例如违反唯一性、死锁(访问相同数据而产生的竞争)、运算溢出等。在 SQL 语句解析的过程中发生错误(例如语法错误),由于未对数据产生任何影响,因此不会产生语句级回滚。
SQL> select PARA_NAME,PARA_VALUE,PARA_TYPE,DESCRIPTION from v$dm_ini where para_name='ROLL_ON_ERR';
-
事务锁定
当事务在对某个数据库对象进 行操作前,需要先对其封锁。封锁后事务就对该数据库对象有了一定的控制,在该事务释放 锁之前,其他的事务不能对此数据库对象进行相应操作。
1、锁模式
锁模式指定并发用户如何访问锁定资源
(1)共享锁:
Share Lock,简称S锁,用于读操作,防止其他事务修改正在访问的对象,这种封锁模式允许多个事务同时并发读取相同的资源,但是不允许任何事务修改这个资源
(2)排他锁:
Exclusive Lock,简称 X 锁,用于写操作,以独占的方式访问对象,不允许任何其他事务访问被封锁对象;防止多个事务同时修改相同的数据,避免引发数据错误。一般在修改对象定义时使用
(3)意向锁:
Intent Lock ,用于读取或修改被访问对象数据时使用,多个事务可以同时 对相同对象上意向锁。
种类:
意向共享锁(Intent Share Lock,简称 IS 锁):一般在只读访问对象时使用。
意向排他锁(Intent Exclusive Lock,简称 IX 锁):一般在修改对象数据时使用。
2、锁粒度
(1)TID锁:
以事务号为封锁对象,为每个活动事务生成一把 TID 锁,代替了其他数据库行 锁的功能,防止多个事务同时修改同一行记录。DM 实现的是行级多版本,每一行记录隐含 一个 TID 字段,用于事务可见性判断。
执行 INSERT、DELETE、UPDATE 操作时,设置事务号到 TID 字段。这相当于隐式地 对记录上了一把 TID 锁,INSERT、DELETE、UPDATE 操作不再需要额外的行锁,避免了 大量行锁对系统资源的消耗。只有多个事务同时修改同一行记录时,才会产生新的 TID 锁。
(2)对象锁
对象锁是 DM 新引入的一种锁,通过统一的对象 ID 进行封锁,将对数据字典的封锁和 表锁合并为对象锁,以达到减少封锁冲突、提升系统并发性能的目的。
数据字典锁:用来保护数据字典对象的并发访问,解决 DDL 并发和 DDL/DML 并发 问题,防止多个事务同时修改同一个对象的字典定义,确保对同一个对象的 DDL 操作是串行执行的。并防止一个事务在修改字典定义的同时,另外一个事务修改对 应表的数据。
表锁:表锁用来保护表数据的完整性,防止多个事务同时采用批量方式插入、更新 一张表,防止向正在使用 FAST LOADER 工具装载数据的表中插入数据等,保证这些优化后数据操作的正确性。避免对存在未提交修改的表执行 ALTER TABLE、TRUNCATE TABLE 操作。
独占访问(EXCLUSIVE ACCESS),不允许其他事务修改对象,不允许其他事务访问对象,使用 X 方式封锁
独占修改(EXCLUSIVE MODIFY),不允许其他事务修改对象,允许其他事务共享访问对象,使用 S + IX 方式封锁
共享修改(SHARE MODIFY),允许其他事务共享修改对象,允许其他事务共享访问对象,使用 IX 方式封锁
共享访问(SHARE ACCESS),允许其他事务共享修改对象,允许其他事务共享访问对象,使用 IS 方式封锁。
(3)显示锁定表
用户可以根据自己的需要显式的对表对象进行封锁。
--lock_mode锁定模式:INTENT SHARE(意向共享)、INTENT EXCLUSIVE(意向排他)、SHARE(共享)、EXCLUSIVE(排他)
--nowait:若不能立即上锁成功则like返回报错信息,不再等待
LOCK TABLE tab_name IN lock_mode MODE [NOWAIT];
意向共享:不允许其他事务独占修改该表。意向共享锁定后,不同事务可以同时增、 删、改、查该表的数据,也支持在该表上创建索引,但不支持修改该表的定义;
意向排他:不允许其他事务独占访问和独占修改该表。被意向排他后,不同事务可 以同时增、删、改、查该表的数据,不支持在该表上创建索引,也不支持修改该表 定义;
共享:只允许其他事务共享访问该表,仅允许其他事务查询表中的数据,但不允许 增、删、改该表的数据;
排他:以独占访问方式锁定整个表,不允许其他事务访问该表,是封锁力度最大的 一种封锁方式。
3、V$LOCK
查看当前系统中锁的状态
--查看锁
SELECT * FROM V$LOCK;
-
多版本
DM 数据库基于物理记录和回滚记录实现行级多版本支持,数据页中只保留物理记录的 最新版本,通过回滚记录维护历史版本,所有事务针对特定的版本进行操作。
1、历史数据获取:
当物理记录对当前事务不可见时,根据物理记录和回滚记录的 RPTR 指针,向前回溯一 个历史版本记录,通过此历史版本记录的 TID 字段,依据事务可见性原则判断此版本的记 录对当前事务是否可见。如可见即获取到了满足当前事务的历史版本数据;如不可见则根据 RPTR 指针继续向前回溯。如果一直不能找到对当前事务的可见版本(例如此记录是一个活 动事务插入的新记录),则此记录将不会添加到查询结果集中。
2、回滚段自动清理:
由于需要根据回滚记录回溯、还原物理记录的历史版本信息,因此不能在事务提交时立 即清除当前事务产生的回滚记录。但是,如果不及时清理回滚段,可能造成回滚段空间的不 断膨胀,占用大量磁盘空间。 DM 提供了自动清理、回收回滚段空间的机制。系统定时(缺省是每间隔 1 秒)扫描回 滚段,根据回滚记录的 TID,判断是否需要保留回滚记录,清除那些对所有活动事务可见的 回滚记录空间。
-
事务隔离级
脏读(DirtyRead)
所谓脏读就是对脏数据的读取,而脏数据所指的就是未提交的已修改数据。
不可重复读(Non-RepeatableRead)
一个事务先后读取同一条记录,但两次读取的数据不同,我们称之为不可重复读
幻像读(PhantomRead)
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其 查询条件的新数据,这种现象就称为幻像读。
1、读提交隔离级
DM 数据库的读提交隔离可以确保只访问到已提交事务修改的数据,保证数据处于一致 性状态,能够满足大多数应用的要求,并最大限度的保证系统并发性能,但可能会出现不可重复读取和幻像读。
--设定事务为读提交隔离级
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
2、串行化隔离级
消除不可重复读取或幻像读。串行化事务的查询本身不会增加任何代价,但修改数据可能引发“串行化 事务被打断”错误。
者应该充分考虑串行化事务带来的回滚及重做事务的开销,从应用逻辑上避免对相同数据行的激烈竞争导 致产生大量事务回滚。
--设定事务为串行化隔离级
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
3、读未提交隔离级
在使用这个隔离级别时,有可能发 生脏读、不可重复读和幻像。一般来说,读未提交隔离级别通常只用于访问只读表和只读视 图,以消除可见性判断带来的系统开销,提升查询性能。
--设定事务为读未提交隔离级
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITED;
4、只读事务
只读事务只能访问数据, 但不能修改数据。并且只读事务不会改变事务原有的隔离级。
--设定事务为只读事务
SET TRANSACTION READ ONLY;
当设置问只读事务后,DML操作报错
-
锁等待与死锁检测
阻塞:当一个事务正在占用某个资源的锁,此时另一个事务正在请求这个资源上与第一个锁相冲突的锁类型时,就会发生阻塞。
--查询原始数据
select * from DMHR.TEST01;
--分别在两个session执行不同的UPDATE语句,更新同一笔数据
update DMHR.TEST01 SET C2='test_lock1' where C1=1;
update DMHR.TEST01 SET C2='test_lock2' where C1=1;
session1 提交后,session2 执行成功
死锁包括两个或者多个已阻塞事务,它们之间形成了等待环,每个都等待其他事务释放锁
--在session1执行一个UPDATE语句,不提交
update DMHR.TEST01 SET C2='test_lock1' where C1=3;
--在session2执行一个INSERT语句,不提交
INSERT INTO DMHR.TEST01 VALUES(4,'test_lock2');
--在session1执行一个INSERT语句,C1是唯一键,与session2 c1值相同
INSERT INTO DMHR.TEST01 VALUES(4,'test_lock2');
--在session1执行一个UPDATE语句,更新同一笔数据
update DMHR.TEST01 SET C2='test_lock2' where C1=3;
test01原始数据:
死锁会通过使session2执行语句失败的方式,自动解锁
SESSION2 先执行commit;session1 继续向下执行
session1的update语句成功,session2 的insert语句成功
- 闪回
闪回技术主要是通过回滚段存储的 UNDO 记录来完成历史记录的还原。
ENABLE_FLASHBACK=1,开启闪回功能,0关闭闪回功能,默认0
select PARA_NAME,PARA_VALUE,PARA_TYPE,DESCRIPTION from v$dm_ini where para_name='ENABLE_FLASHBACK';
开启闪回功能。DM 会保留回滚段一段时间,回滚段保留的 时间代表着可以闪回的时间长度。由 UNDO_RETENTION 参数指定
select PARA_NAME,PARA_VALUE,PARA_TYPE,DESCRIPTION from v$dm_ini where para_name='UNDO_RETENTION';
开启闪回功能后,DM 会在内存中记录下每个事务的起始时间和提交时间。通过用户指 定的时刻,查询到该时刻的事务号,结合当前记录和回滚段中的 UNDO 记录,就可以还原出 特定事务号的记录。即指定时刻的记录状态。从而完成闪回查询。闪回查询功能完全依赖于 回滚段管理,对于 DROP 等误操作不能恢复。