转://Oracle 事务探索与实例(一)

数据库版本

[email protected]>select* from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise EditionRelease 11.2.0.1.0 - 64bit Production

PL/SQLRelease 11.2.0.1.0 - Production

CORE    11.2.0.1.0      Production

TNS forLinux: Version 11.2.0.1.0 - Production

NLSRTLVersion 11.2.0.1.0 - Production

事务那些事儿

1.什么是事务:事务是一组操作序列,这些操作要么都完成,要么都不完成,它是一个不可分割的操作单元。关系型数据库最核心的价值体现。说白了为了完成一件事而做的n个步骤,这n个步骤是有前后顺序的,必须按照A->B->C->D的逻辑顺序来执行,事务是数据库维护数据一致性的单位,例如多个会话同时读取同一数据的问题。

关系型数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。

场景:银行转账结算购物订票系统

非关系型数据库中,一个事务可以是一个操作,但操作之间没有关系,相互独立的。

比如:推荐系统日志分析网站搜索

用例子说明事务的四个属性和自动提交功能

事务的属性ACID

原子性(Atomicity):一个事务是一个不可分割的整体,事务中的操作要么都完成,要么都失败。

实例

[email protected]>conn leo1/leo1

Connected.

[email protected]>drop table leo1 purge;                  清理环境

Table dropped.

[email protected]>create table leo1 (x number,ynumber);     创建表

Table created.

[email protected]>insert into leo1 values(1,1);               执行DML操作

1 row created.

[email protected]>update leo1 set x=2 where x=1;

1 row updated.

[email protected]>delete from leo1 where y=1;

1 row deleted.

[email protected]>commit;

Commit complete.

上面我们执行了三条sql语句,都属于一个事务,当commit的时候表示事务完成,这三条sql全部生效,如果rollback这三条sql全部失败,不存在有的完成有的失败,因为它们是一个不可再分割的整体。

一致性(Consistency):指数据库的一种状态的一致性,具体来说不可违反约束,不可违反规则,所谓的一致性就是一种人为规则,例如定义一个主键,插入2条一样的数据就违反了一致性条件。

实例

[email protected]>drop table leo2 purge;                                            清理环境

Table dropped.

[email protected]>create table leo2 (x number,ynumber,constraint pk_leo2 primary key(x));  x列有主键

Table created.

[email protected]>insert into leo2 values(1,1);

1 row created.

[email protected]>insert into leo2 values(1,2);                     当插入的值一样时违反了一致性

insert into leo2 values(1,2)

*

ERROR at line 1:

ORA-00001: unique constraint (LEO1.PK_LEO2)violated

隔离性(isolation):未提交的事务其他会话不可见。

实例

会话一

[email protected]>select * from leo2;               表里只有1条记录

X          Y

---------- ------------------- ----------

1          1

[email protected]>insert into leo2 values(2,2);        新插入一条

1 row created.

[email protected]>select * from leo2;               此时表里有2条记录,但未有提交

X          Y

---------- ------------------- ----------

1          1

2          2

会话二

[[email protected] flashback_area]$sqlplus leo1/leo1    连接新会话

[email protected]>select * from leo2;      只能看到已提交事务的数据,未提交的事务看不到

X          Y

---------- ----------

1          1

持久性(Durability):事务一旦提交就不可更改,永久有效。

实例

[email protected]>drop table leo3 purge;

Table dropped.

[email protected]>create table leo3 (x number,ynumber);

Table created.

[email protected]>insert into leo3 values(1,1);

1 row created.

[email protected]>commit;

Commit complete.

[email protected]>select * from leo3;

X          Y

---------- ----------

1          1

[email protected]>rollback;

Rollback complete.

[email protected]>select * from leo3;

X          Y

---------- ----------

1          1

事务一旦commit,你再rollback也是无效的,已经插进去了。

事务是以第一个DML语句作为开始

以下面其中之一作为结束

(1)commit or rollback

(2)DDL or DCL

(3) 用户session正常结束退出sqlplus

(4) 系统正常结束or终止

事务自动提交,我们可以设置oracle自动提交事务

实例

[email protected]>show autocommit;                  默认是不启动自动提交的

autocommit OFF

[email protected]>set autocommit on;                 手工启动

[email protected]>show autocommit;

autocommit IMMEDIATE

[email protected]>insert into leo3 values(2,2);           当插入数据的同时就提交

1 row created.

Commit complete.

[email protected]>select * from leo3;

X          Y

---------- ----------

1         1

2          2

[email protected]>rollback;                           此时回滚已无效

Rollback complete.

[email protected]>select * from leo3;

X          Y

---------- ----------

1          1

2          2

[email protected]>set autocommit off;                  我们不建议开启事务自动提交功能

Oracle下演示Nonrepeatable Read PhantomRead的例子,给出SQL演示过程。

Non-repeatable Read不可重复读:在一个事务中,同样的数据被2次读取,得到不同的结果集

实例

Leo帮tiger一起买2张飞机表去肯尼亚看大象

[email protected]>drop table leo6 purge;

Table dropped.

[email protected]>create table leo6 (namevarchar2(10),ticket_type varchar2(20),price number);

Table created.

[email protected]>insert into leo6values(‘leo‘,‘plane_ticket‘,100);

1 row created.

[email protected]>insert into leo6values(‘tiger‘,‘plane_ticket‘,100);

1 row created.

[email protected]>commit;

Commit complete.

[email protected]>select * from leo6;

NAME      TICKET_TYPE               PRICE

---------- -------------------- ----------

leo         plane_ticket                100

tiger        plane_ticket                100

飞机票的价格都是100$,2个人一共200$

Leo查询的价格

[email protected]>select sum(price) both_pricefrom leo6;

BOTH_PRICE

------------------

200

在过行李安检的时候,发现tiger行李超重,原来tiger非常有爱心,给大象带了花生+毛豆,根据规定超重行李是要补交托运费的。

机场又加了100元托运费

[email protected]>update leo6 set price=200where name=‘tiger‘;

1 row updated.

[email protected]>select * from leo6;

NAME      TICKET_TYPE               PRICE

---------- -------------------- ----------

leo        plane_ticket                100

tiger       plane_ticket                200

[email protected]>commit;

Commit complete.

Leo再次查询价格时,总价变成300了

[email protected]>select sum(price) both_pricefrom leo6;

BOTH_PRICE

------------------

300

不可重复读在数据库中是可能出现的,所以要注意一下,上面leo和机场是两个独立会话

Phantom Read幻读:在一个事务中,同样的sql被2次执行,得到不同的结果集。

实例

翻山越岭跋山涉水终于来到了广阔的非洲大草原真是大象遍地走春风吹又生,tiger肴有兴致的数起了大象

Tiger 查询的结果

[email protected]>drop table leo7 purge;

Table dropped.

[email protected]>create table leo7 (namevarchar2(10),num number);

Table created.

[email protected]>insert into leo7values(‘a‘,1);

1 row created.

[email protected]>insert into leo7values(‘b‘,1);

1 row created.

[email protected]>commit;

Commit complete.

[email protected]>select count(*) from leo7;                    第一天发现了2只

COUNT(*)

-----------------

2

傍晚有一只小象跑了过来

[email protected]>insert into leo7values(‘c‘,1);

1 row created.

[email protected]>commit;

Commit complete.

第二天tiger又查询了一遍,这次发现了3只

[email protected]>select count(*) from leo7;

COUNT(*)

-----------------

3

小结:上述两个生动的例子展现了Non-repeatableRead不可重复读和Phantom Read幻读的过程,大家一定要好好体会里面的含义,理解这两种不同的数据读取方式。

Oracle设计一个场景,会导致Non-repeatableRead,然后选择一种事务隔离等级来避免它的发生,给出SQL演示过程。

场景:tiger在游玩非洲大草原之后,选择从海路回家,在走到索马里海岸的时候,有幸被海盗光顾,请他上岸吃海鲜,这次海盗拿出了不劳而获的敬业精神,赎金10000$,三天之内交换人质,一手交钱,一手交货。由于历来海盗的诚信记录并不是很光彩照人,我们模拟了一下可能的突发事件。

首先海盗提出条件,赎金10000$,还为此特意做了一个排行榜

[email protected]>create table leo8 (namevarchar2(20),cost int);          排行榜清单

Table created.

[email protected]>insert into leo8values(‘tiger‘,10000);                  插入tiger信息

1 row created.

[email protected]>commit;

Commit complete.

[email protected]>select * from leo8 whererownum<=1;                 我们看到tiger排在第一位

NAME                    COST

---------------------------------------------------------------

tiger                     10000

上面的信息是我们自己查询的情况,突然海盗得知tiger是中国知名的IT专家,国家的财富和人才。本着生意人的精明头脑,高价值的人当然换取的条件也水涨船高,海盗偷偷修改了赎金数,变成20000$

海盗

[email protected]>update leo8 set cost=20000where cost=10000;

1 row updated.

[email protected]>commit;

Commit complete.

当我们交钱的时候发现tiger升值了,哎呦我去~ 这不打劫嘛!

[email protected]>select * from leo8 whererownum<=1;

NAME                    COST

---------------------------------------------------------------

tiger                     20000

为了防止这种事情发生,我们可以使用Oracle的Read-only事务隔离等级和Serializable事务隔离等级来避免这种事情发生,这两种事务隔离等级非常相似,因此我们选择较常用的Serializable来给大家演示。

Read-only事务隔离等级:只能看到事务开始时所有提交的改变,自身不允许DML操作。

Serializable事务隔离等级:只能看到事务开始时所有提交的改变和自身的改变。

当海盗告知我们赎金是10000$的时候,我们先开出了清单

[email protected]>drop table leo8 purge;

Table dropped.

[email protected]>create table leo8 (namevarchar2(20),cost int);     tiger清单

Table created.

[email protected]>insert into leo8values(‘tiger‘,10000);

1 row created.

[email protected]>commit;

Commit complete.

[email protected]>set transaction isolationlevel serializable;         我们设置好了隔离等级

Transaction set.

[email protected]>select * from leo8 whererownum<=1;             没错是10000$

NAME                    COST

---------------------------------------------------------------

tiger                     10000

海盗又故伎重演,想把价格提高到20000$,这是另一个会话

[email protected]>update leo8 set cost=20000where cost=10000;      已经更新

1 row updated.

[email protected]>commit;

Commit complete.

到了较赎金的时候,我们又查询了一次

[email protected]>select * from leo8 whererownum<=1;

NAME                    COST

---------------------------------------------------------------

tiger                     10000

good,完美封杀了海盗邪恶企图,数据没有变化,但并不是说数据没有被修改,由于启动事务隔离策略,其他事务所做的修改我们是看不到的。Serializable只对当前事务有效,不对另外事务有效。

小结:Oracle中所有事务隔离等级都是依赖undo实现的。什么时候使用Serializable隔离等级好呢,当修改操作比较短的事务,事务中存在多条sql需要数据从事务开始时就保持一致,这样的场景适合。

用示例比较OracleRead committed Serializable 事务隔离等级的区别,给出SQL演示过程。

Read committed读已提交事务隔离等级:Oracle 默认隔离等级,支持不可重复读和幻读。这两种数据读写方式在第四题中已经完全阐述了,这里不在重复。

Serializable 事务隔离等级:只能看到事务开始时所有提交的改变和自身的改变,不支持不可重复读和幻读,事务开始是什么样子,结果就是什么样子,其他用户影响不了这个事务。

会话A

[email protected]>create table leo9(x int,yint);                 创建表

Table created.

[email protected]>insert into leo9values(100,100);              插入一行

1 row created.

[email protected]>commit;                                  提交

Commit complete.

[email protected]>set transaction isolationlevel serializable;       启动Serializable 事务隔离等级

Transaction set.

[email protected]>select * from leo9;

X          Y

---------- ----------------- ----------

100       100

会话B,我们用另一个会话不管怎么修改leo9表,都不会影响会话A事务

[email protected]>insert into leo9values(200,200);

1 row created.

[email protected]>commit;

Commit complete.

[email protected]>insert into leo9values(300,300);

1 row created.

[email protected]>commit;

Commit complete.

会话A,还是一条数据

[email protected]>select * from leo9;

X          Y

---------- ----------------- ----------

100       100

会话A自己修改的内容在事务中是生效的

[email protected]>insert into leo9values(400,400);          我们插入一条记录

1 row created.

[email protected]>select * from leo9;                     在本事务中是可以看到的

X          Y

---------- ----------

400        400

100        100

[email protected]>commit;                              一旦事务结束,Serializable 事务隔离等级就会失效

Commit complete.

会话A,又可以看到所有的记录了

[email protected]>select * from leo9;

X          Y

---------- ----------

400        400

100        100

200        200

300        300

两种事务隔离等级的比较

Read committed                       V.S                      Serializable   Transactions

支持SQL92标准支持SQL92标准

读取物化视图维护语句级一致性维护事务级一致性

事务一致性支持语句级支持事务级

行级锁支持支持

读锁定写不支持不支持

写锁定读不支持不支持

非行级锁不支持不支持

行级锁支持支持

事务锁等待支持支持

小结:Serializable事务隔离等级作用域是一个事务,超出这个事务就无效了。

事务属性   Phantom Read   Non-repeatableRead   Read committed   Serializable

时间: 2024-08-23 04:17:34

转://Oracle 事务探索与实例(一)的相关文章

转://Oracle 事务探索与实例(二)

一数据库版本 [email protected]>select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production PL/SQL Release 11.2.0.1.0 - Product

Oracle之索引(Index)实例讲解 - 基础

Oracle之索引(Index)实例讲解 - 基础 索引(Index)是关系数据库中用于存放表中每一条记录位置的一种对象,主要目的是加快数据的读取速度和数据的完整性检查.索引的建立是一项技术性要求非常高的工作. 一般在数据库设计阶段就要考虑到如何设计和创建索引. 1. 创建索引 创建索引的语法: CREATE [UNIQUE] INDEX [schema.] index ON [schema.] table (column [ASC | DESC], column [ASC | DESC]...

[转]Oracle DB 管理ASM实例

? 描述使用ASM 的好处 ? 管理ASM 实例 ? 创建和删除ASM 磁盘组 ? 扩展ASM 磁盘组 ? 通过使用各种实用程序检索ASM 元数据 Automatic Storage Management Automatic Storage Management (ASM) 将文件系统与卷管理器纵向集成在一起,这是一项专门为Oracle DB 文件建立的技术.使用ASM 可管理单个对称多处理(SMP) 计算机,或通过管理集群的多个节点来支持Oracle Real Application Clus

oracle事务和锁

数据库事务概括 1. 说明 一组SQL,一个逻辑工作单位,执行时整体修改或者整体回退. 2.事务相关概念 1)事务的提交和回滚:COMMIT/ROLLBACK 2)事务的开始和结束 开始事务:连接到数据库,执行DML.DCL.DDL语句 结束事务: 1. 执行DDL(例如CREATE TABLE),DCL(例如GRANT),系统自动执行COMMIT语句 2. 执行COMMIT/ROLLBACK 3. 退出/断开数据库的连接自动执行COMMIT语句 4. 进程意外终止,事务自动rollback 5

Oracle事务

Oracle事务的ACID特性 原子性Atomicity:事务中的所有动作要么都发生,要么都不发生. 一致性Consistency:事务将数据库从一种状态转变为下一种一致状态. 隔离性Isolation:一个事务的影响在该事务提交前对其他事务时不可见的. 持久性Durability:事务一旦提交,其影响就是永久性的. 事务控制语句 事务隐式开始 事务必须显示结束(Commit.Rollback) Commit 会结束事务,并使得已做的修改持久的保存在数据库中 Rollback 会结束事务,并撤销

Oracle 事务的開始与结束

事务是用来切割数据库活动的逻辑工作单元,事务即有起点,也有终点: 当下列事件之中的一个发生时,事务就開始了: 连接到数据库上,并运行了第一天 DML 语句: 当前一个事务结束后,又输入了另外一条 DML 语句: 当下列事件之中的一个发生时,事务就结束了: 运行 COMMIT 或 ROLLBACK语句: 运行一条 DLL语句,比如 CREATE TABLE 语句:在这样的情况下, 会自己主动运行 COMMIT 语句: 运行一条 DCL语句,比如GRANT语句:在这样的情况下,会自己主动运行COMM

Oracle 事务操作(事务的回滚与提交)

在看本文之前,请确保你已经了解了Oracle事务和锁的概念即其作用,不过不了解,请参考数据库事务的一致性和原子性浅析和Oracle TM锁和TX锁 1.提交事务 当执行使用commit语句可以提交事务.当执行了commit语句后,会确认事务的变化.结束事务.删除保存点.释放锁.在此之前,与当前事务相关的数据都会被加锁,直到当前事务进行了commit操作,如果在这个过程中有其他回话试图操作相关数据,(这些数据已经被当前事务加锁),那么其他回话会进行等待,或者直接返回错误. 注意:只有在提交事务之后

oracle事务知识点小结

DML语句流程 1 获取事务锁和ITL2 锁定候选行3 生成redo4 生成undo5 生成redo record写入log buffer并更改数据块 事务提交1 分配SCN2 更新事务表,将事务槽状态改为0x093 回收undo块4 创建commit redo record5 将redo从log buffer刷新6 释放表锁和行锁 锁一个事务由1个TX和若干TM组成,而回滚savepoint不会释放TX锁: ITL通过XID指向事务槽,进而指向undo记录,其UBA也指向undo记录:两者区别

oracle事务(转)

今天温习oracle事务,记录如下: 事务定义            事务是保持数据的一致性,它由相关的DDL或者DML语句做为载体,这组语句执行的结果要么一起成功,要么一起失败. 我们知道SQL92标准定义了数据库事务的四个特点: 原子性 (Atomicity) :一个事务里面所有包含的SQL语句是一个执行整体,不可分割,要么都做,要么都不做 一致性 (Consistency) :事务开始时,数据库中的数据是一致的,事务结束时,数据库的数据也应该是一致的 隔离性 (Isolation):