4月29日

  最近一段时间一直在写(其实是摘抄的笔记)oracle的文章,不能说精通,收获还是有的。基本可以告一段落了。花了两个月的时间。

oracle数据类型简述

oracle提供了22种不同的数据类型。

一、数据类型

1、char
char是一个定长字符串,会用空格填充来达到其最大长度。如果该列没有插入数据为null,插入数据没有到定义的长度,用空格填充。

2、nchar
这是一个包含unicode格式数据的定长字符串。

3、varchar2
目前这也是varchar的同义词。这是一个变长字符串,与char类型不同,它不会用空格填充至最大长度。

4、nvarchar2
这是一个包含unicode格式数据的变长字符串。

5、raw
这是一种变长二进制数据类型,这说明采用这种数据类型存储的数据不会发生字符集转换。可以把它看作由数据库存储的信息的二进制字节串。

使用类似于char,存储的是char的二进制值。(我没用过)
继续阅读oracle数据类型简述

oracle数据库对象-索引

一、索引的概念

索引类似于查字典,通过拼音、笔画,只要几步就能查到所要的字。数据库里,通过索引,只要少量的读,就能找到所需的记录。

使用索引需要找到一个平衡点,索引太多会影响DML语句的速度,因为要写索引表。索引太少又不能提高查询速度。

二、B*树索引


1、B*树索引:我们所说的“传统”的索引。create index 创建的索引默认是B*索引。

B*数索引类似于一颗二叉树,但并不是二叉树。B*树中的“B”不代表二叉(binary),而代表平衡(balanced)。

B*树的特点之一是:所有叶子块都应该在树的同一层上。

这一层也称为索引的高度(height),这说明所有从索引的根块到叶子块的遍历都会访问同样数目的块。也就是说,对于形如“SELECT INDEXED_COL FROM T WHERE INDEXED_COL = :X”的索引,要到达叶子块来获取第一行,不论使用的:X值是什么,都会执行同样数目的I/O。

换句话说,索引是高度平衡的(height balanced)。大多数B*树索引的高度都是2或者3,即使索引中有数百万行记录也是如此。这说明,一般来讲,在索引中找到一个键只需要执行2或3次I/O。
继续阅读oracle数据库对象-索引

oracle数据库对象-表的分类

oracle中的一个表最多可以有1000列。

oracle中有9种类型的表:

1、堆组织表(heap organized table)
就是“普通”的标准数据库表。数据以堆的方式管理。堆组织表中记录是无序的,不以某种特定顺序来放置。

2、索引组织表(index organized table)
索引组织表的数据都存储在与其关联的索引中,对表的添加、更新、删除,只会导致索引的更新。查询时必须根据索引去查询数据。

索引组织表必须设定主键。

create table indextable (
id varchar2(10),
name varchar2(20),
constraint pk_idx primary key (id)
)
organization index;

insert into indextable values ('1', '1');
insert into indextable values ('2', '2');

对索引组织表查询:

select * from indextable where id = '2';
select * from indextable where name = '2';

第一个查询的是主键,执行计划走的是INDEX UNIQUE SCAN。第二个查询的非索引字段,执行计划走的是INDEX FAST FULL SCAN。说明索引组织表的数据是跟在索引后面的,执行计划会自动根据索引来查询。
继续阅读oracle数据库对象-表的分类

oracle redo和undo简述

一、redo

重做日志文件(redo log file)是数据库的事务日志。oracle有在线重做日志和归档重做日志。

重做日志文件都用于恢复,万一实例失败或介质失败,它们就能恢复数据库到这个“意外”发生前的时间点。

二、undo

undo用于取消一条语句或一组语句的作用。

undo在数据库内部存储在一组特殊的段中,这称为undo段(undo segment)。“回滚段”(rollback segment)和“undo 段”(undo segment)一般认为是同义词。

undo操作数据库只是逻辑地恢复到原来的样子,所有修改都被逻辑地取消,但是数据结构以及数据库块本身在回滚后可能大不相同。

oracle回滚时,它实际上会做与先前逻辑上相反的工作。对于每个insert,oracle会完成一个delete。对于每个delete,oracle会执行一个insert。对于每个update,oracle则会执行一个“反update”,或者执行另一个update将修改前的行放回去。
继续阅读oracle redo和undo简述

oracle事务简述

一、事务的概念

事务会把数据库从一种一致状态转变为另一种一致状态,这就是事务的任务。

oracle的事务提供了ACID特征:

原子性(atomicity):事务中的所有动作要么都发生,要么都不发生。

一致性(consistency):事务将数据库从一种一致状态转变为下一种一致状态。

隔离性(isolation):一个事务的影响在该事务提交前对其他事务都不可见。

持久性(durability):事务一旦提交,其结果就是永久性的。

其中最重要的特性是它的原子性。

二、事务控制语句

一定要显式地使用commit或rollback来终止你的事务。

commit:要想使用这个语句的最简形式,只需发出commit。也可以更详细一些,写为commit work,不过这二者是等价的。commit会结束你的事务,并使得已做的所有修改成为永久性的(持久保存)。commit语句还有一些扩展用于分布式事务中。利用这些扩展,允许增加一些有意义的注释为commit加标签(对事务加标签),以及强调提交一个可疑的分布式事务。

rollback:要想使用这个语句的最简形式,只需发出rollback。同样地,你也可以罗嗦一些,写为rollback work,但是二者是等价的。回滚会结束你的事务,并撤销正在进行的所有未提交的修改。为此要读取存储在回滚段/undo段中的信息,并把数据库块恢复到事务开始之前的状态(后面我将把回滚段/undo段统称为undo段,Oracle 10g中都喜欢用这个词)。

savepoint:savepoint允许你在事务中创建一个“标记点”(marked point),一个事务中可以有多个savepoint。

rollback to :这个语句与savepoint命令一起使用。可以把事务回滚到标记点,而不回滚在此标记点之前的任何工作。所以,可以发出两条update语句,后面跟一个savepoint,然后又是两条delete语句。如果执行delete语句期间出现了某种异常情况,而且你捕获到这个异常,并发出rollback to savepoint命令,事务就会回滚到指定的savepoint,撤销delete完成的所有工作,而update语句完成的工作不受影响。

set transaction:这条语句允许你设置不同的事务属性,如事务的隔离级别以及事务是只读的还是可读写的。使用手动undo管理时,还可以使用这个来指示事务使用某个特定的undo段,不过不推荐这种做法。

最常用的控制语句就是commit和rollback。savepoint语句的用途有点特殊。oracle在内部频繁地使用了这个语句,你会发现这语句在你的应用中可能也有用。
继续阅读oracle事务简述

oracle并发控制简述(多版本和读一致性)

一、什么是并发控制

并发控制(concurrency control)是数据库提供的函数集合,允许多个人同时访问和修改数据。前一章曾经说过,锁(lock)是oracle管理共享数据库资源并发访问,并防止并发数据库事务之间“相互干涉”的核心机制之一。

总结一下,oracle使用了多种锁,包括:

TX锁:修改数据的事务在执行期间会获得这种锁。

TM锁和DDL锁:在你修改一个对象的内容(对于TM锁)或对象本身(对应DDL锁)时,这些锁可以确保对象的结构不被修改。

闩(latch):这是oracle的内部锁,用来协调对其共享数据结构的访问。

oracle的多版本:

多版本是指,oracle能同时物化多个版本的数据,数据读相对于某个时间点有一致的结果。

多版本有一个很好的副作用,即数据的读取器(reader)绝对不会被数据的写入器(writer)所阻塞。换句话说,写不会阻塞读。

二、事务隔离级别

事务隔离级别是根据3个“现象”定义的,以下就是给定隔离级别可能允许或不允许的3种现象:

脏读(dirty read):这个词不仅不好听,实际上也确实是贬义的。你能读取未提交的数据,也就是脏数据。只要打开别人正在读写的一个OS文件(不论文件中有什么数据),就可以达到脏读的效果。如果允许脏读,将影响数据完整性,另外外键约束会遭到破坏,而且会忽略惟一性约束。

不可重复读(nonrepeatable read):这意味着,如果你在T1时间读取某一行,在T2时间重新读取这一行时,这一行可能已经有所修改。也许它已经消失,有可能被更新了,等等。

幻像读(phantom read):这说明,如果你在T1时间执行一个查询,而在T2时间再执行这个查询,此时可能已经向数据库中增加了另外的行,这会影响你的结果。与不可重复读的区别在于:在幻像读中,已经读取的数据不会改变,只是与以前相比,会有更多的数据满足你的查询条件。

ANSI/ISO SQL92标准中定义了4种事务隔离级别:

1、序列化(serializable)

最高隔离级别。系统中所有的事务都是一个接一个执行的。因此也就不会发生任何事务之间的冲突问题。

2、可重复读(repeatable read)

一个事务所读取的数据记录不允许被其他事务所修改。

3、读已提交(read committed)

该级别允许其他事务修改当前事务所读取的数据记录,并且那个事务提交之后,当前事务可以看到修改后的数据。

4、读未提交(read uncommitted)

该级别允许其他事务修改当前事务所读取的数据记录,并且那个事务尚未提交时,当前事务就可以看到修改后的数据。即允许脏读。
继续阅读oracle并发控制简述(多版本和读一致性)

oracle锁简述

不同的数据库它的锁定机制是不同的,即使表面上看是一样的(都是行级锁),但是他们的实现方法也是完全不同的。

一、综述

在oracle中,你会了解到:

事务是每个数据库的核心,它们是“好东西” 。

应该延迟到适当的时刻才提交。不要太快提交,以避免对系统带来压力。这是因为,如果事务很长或很大,一般不会对系统有压力。相应的原则是:在必要时才提交,但是此前不要提交。事务的大小只应该根据业务逻辑来定。

只要需要,就应该尽可能长时间地保持对数据所加的锁。这些锁是你能利用的工具,而不是让你退避三舍的东西。锁不是稀有资源。恰恰相反,只要需要,你就应该长期地保持数据上的锁。锁可能并不稀少,而且它们可以防止其他会话修改信息。

在oracle中,行级锁没有相关的开销,根本没有。不论你是有1个行锁,还是1000000个行锁,专用于锁定这个信息的“资源”数都是一样的。当然,与修改1行相比,修改1000000行要做的工作肯定多得多,但是对1000000行锁定所需的资源数与对1行锁定所需的资源数完全相同,这是一个固定的常量。

不要以为锁升级“对系统更好”(例如,使用表锁而不是行锁)。在oracle中,锁升级(lock escalate)对系统没有任何好处,不会节省任何资源。也许有时会使用表锁,如批处理中,此时你很清楚会更新整个表,而且不希望其他会话锁定表中的行。但是使用表锁绝对不是为了避免分配行锁,想以此来方便系统。

二、悲观锁和乐观锁

1、悲观锁(pessimistic locking)

在试图更新之前我们就把行锁住了,因为我们很悲观,对于这一行能不能保持未改变很是怀疑。

如何实现悲观锁:加for update nowait

保证最初读出数据之后,在我们更新之前数据没有改变。

2、乐观锁(optimistic locking)

把所有锁定都延迟到即将执行更新之前才做。
可以在update中同时保留新值和旧值,例如
update emp set sal = 2000 where empno = 100 and sal = 1000;
乐观锁如果update返回0行,说明数据在查询之后被修改了。
继续阅读oracle锁简述

oracle进程简述

oracle中的各个进程要完成某个特定的任务或一组任务,每个进程都会分配内部内存(PGA 内存)来完成它的任务。oracle实例主要有3类进程:

服务器进程(server process):这些进程根据客户的请求来完成工作。我们已经对专用服务器和共享服务器有了一定的了解,它们就是服务器进程。

后台进程(background process):这些进程随数据库而启动,用于完成各种维护任务,如将块写至磁盘、维护在线重做日志、清理异常中止的进程等。

从属进程(slave process):这些进程类似于后台进程,不过它们要代表后台进程或服务器进程完成一些额外的工作。

一、服务器进程

专用服务器(dedicated server)连接,采用专用服务器连接时,会在服务器上得到针对这个连接的一个专用进程。数据库连接与服务器上的一个进程或线程之间存在一对一的映射。

共享服务器(shared server)连接,采用共享服务器连接时,多个会话可以共享一个服务器进程池,其中的进程由oracle实例生成和管理。你所连接的是一个数据库调度器(dispatcher),而不是特意为连接创建的一个专用服务器进程。

这些服务器进程是干重活的进程。在很多情况下,你都会发现这些进程占用的系统CPU时间最多, 因为正是这些进程来执行排序、汇总、联结等等工作,几乎所有工作都是这些进程做的。

二、连接和会话

连接(connection):连接是从客户到oracle实例的一条物理路径。连接可以在网络上建立,或者通过IPC机制建立。通常会在客户进程与一个专用服务器或一个调度器之间建立连接。不过,如果使用oracle的连接管理器(Connection Manager,CMAN),还可以在客户和CMAN之间以及CMAN和数据库之间建立连接。

会话(session):会话是实例中存在的一个逻辑实体。这就是你的会话状态(session state),也就是表示特定会话的一组内存中的数据结构。提到“数据库连接”时,大多数人首先想到的就是“会话” 。你要在服务器中的会话上执行SQL、提交事务和运行存储过程。

连接是物理概念上的,会话是逻辑概念上的,会话是建立在连接之上的,如果会话没有连接它会重新建立一个连接。在一条连接上可以建立0个、一个或多个会话。各个会话是单独而且独立的,即使它们共享同一条数据库物理连接也是如此。也就是说在一个连接里面可以多个用户登录,或一个用户登录多次。
继续阅读oracle进程简述

oracle distinct学习

1、distinct作用是去掉重复值。

select distinct ename from emp;

2、但是往往distinct是用来计算不重复记录的条数,而不是用它来返回不重记录的所有值。

distinct可以这样用:

select count(sal), count(distinct deptno) from emp;

3、如果distinct后面跟多个值,sql是怎么进行处理的呢?

select distinct job, sal from emp;

实际上是distinct后面字段的组合,去掉重复值!

PS:group by后跟多个列是先按第一个列分组,在第一个列分组内再按第二个列分组,以此类推。
PS2:order by后跟多个列是先按第一个列排序,在第一个列排序内再按第二个列排序,以此类推。