Oracle进程
Oracle实例主要有3类进程:server process、background process、slave process。
共享服务器连接强制要求使用Oracle Net,即使在一台机器上也不例外,连接是客户端到Oracle实例的一条物理路径,会话是实例中存在的一个逻辑实体,可在V$SESSION中查询会话。
长事务适合使用专用服务器连接,短事务适合使用专用服务器连接。而且共享服务器可以造成人工死锁,所以共享服务器只适合于OLTP系统,特点是事务短而贫乏,而对数据仓库就很不适用了。
主要的后台进程:
1、 PMON
2、 SMON:数据库级垃圾回收器
3、 RECO
4、 CKPT:只更新数据文件的首部,辅助真正建立检查点的进程(DBWn)
5、 DBWn:负责将脏块写入磁盘
6、 LGWR:负责将SGA中重做日志缓冲区刷新输出到磁盘
7、 ARCn
Oracle锁
两种锁定策略:悲观锁定和乐观锁定
悲观锁定仅用于有状态或者有连接环境中,随着应用服务器的出现,有状态连接数据库已经很少见了。如果你在使用有状态连接,应用可以查询数据而不做任何锁定
乐观锁定把所有锁定都延迟到即将执行更新之前才做。换句话说很可能修改信息时不需要锁,乐观的认为数据库不会被其他用户修改。
实现乐观并发控制的方法有三种,分别是:
1. 一个特殊的列,由数据库应用程序代码或者触发器来维护,代表记录的版本
2. 使用一个校验或散列值
3. 使用新增的Oracle 10g特性ORA_ROWSCN( 每行增加6个字节的开销 )
如果一个会话持有某个资源的锁,而另外一个会话在请求这个资源,会话就被挂起并造成阻塞,应用程序才潜在的bug才是阻塞的根源。
通过select for update可以保证:验证自从你查询之后数据未被修改防止丢失更新,锁住行防止Update和Delete被阻塞
所谓锁升级(lock escalation)是指,系统会降低锁的粒度,数据库系统可以把一个表的100行级锁变成一个表级锁。Oracle从来不会升级锁,但它会执行锁转换,或者称之为锁提升。Oracle会尽可能的降低锁定级别,如果必要会把这个锁转换称为一个更受限的级别,在Oracle中,1个锁的开销和1000000个锁是一样的,都为0。
Oracle主要有3种锁:
1. DML锁
2. DDL锁
3. 内部锁和闩(latch)
Latch是Oracle采用的一种轻量级的低级串行设备,功能上类似与锁。所谓轻量级仅指闩的实现,而不是作用,在Oracle内部会存在大量由于闩导致的竞争。
DML-TX锁,即事务锁,当事务发起第一个修改时会得到TX锁,而且会一直持有,直至事务执行提交或者回滚。TX锁用作一种排队机制,使得其他会话可以等待这个事务执行。Oracle没有一个传统的锁管理器,不会用锁管理器为系统中锁定的每一行维护一个长长的列表。不过,其他的许多数据库是这样做的,对于这些数据库来说,锁是一种稀缺资源,使用得越多,系统要管理的方面就越多。Oracle使用的闩为数据的一个属性,事务只是找到了数据,如果数据没有被锁定,则将其锁定。在Oracle中对数据进行锁定时,行指向事务ID的一个副本,事务ID存储在包含数据行的块中,释放锁时,事务ID却会保留下来。这个事务ID是事务所独有的,标识了回滚段号、槽和序列号。
V$TRANSATION对应每个活动事务都包含了一个条目
V$SESSION显示已经登录的会话
V$LOCK 对应持有所有enqueue队列锁以及正在等待锁的会话,都分别包含一个条目
DML-TM锁,用于确保在修改表内容时,表的结构不会发生改变。即在对表进行操作的时候,防止别的用户DROP或者ALTER来修改表结构。系统中允许的TM锁总数可以由用户来配置,实际上可能设置为0,这并非意味着数据库变成了只读型,而是说不允许DDL语句而已。
DDL锁在是DDL操作上自动加载的,DDL一开始就会提交,它会使你锁执行的所有未执行的工作称为永久性的,即使DDL不成功也会如此。一共有3种类型的DDL锁:
1. 排他DDL锁
2. 共享DDL锁
3. 可中断解析锁:这些锁允许一个对象向另外某个对象注册其依赖性,可中断的
关于latch:是一种锁,设计为只保持极短的一段时间,例如修改一个内存中数据结构所需的时间,用于保护某些内存结构,如数据库块缓冲区缓存或者共享池中的库缓存。一般会在内部使用一种叫做“意愿等待”的模式请求闩。这说明如果闩不可用,请求会话会睡眠一段很短的时间之后再次尝试该操作。还可以采取一种立即模式请求其他的闩,闩的分配相当随机,看运气好坏。
队列锁也是一种更复杂的串行化设备,例如在更新数据库行的时候就会使用到,与闩的区别在于队列锁允许请求者“排队”等待资源。对于闩请求,请求者会话会立即得到通知是否得到了闩,而对于队列锁,请求者会话会阻塞,直至真正得到锁。
Redo和Undo
Redo重做日志文件是数据库的事务日志,Oracle维护着两类重做日志文件:在线(online)重做日志和归档(archived)重做日志,归档重做日志文件实际上就是已经填满的“旧”在线重做日志文件的副本。系统将日志文件填满之后,ARCH进程会在另一个位置建立在线重做日志的部分,也可以在本地和远程位置建立多个另外的副本。如果是实例损坏停止,会使用在线重做日志恢复,如果是介质失败,会使用归档重做日志。Oracle10g之后,有了一种回闪技术,利用回闪技术,可以执行回闪查询,取消数据库表的删除,将表数据置回到过去的某个时间点状态等等。
(每个Oracle数据库都至少有两个在线重做日志组,先写组1,写到快满了的时候切换到组2,循环利用。)
Undo与Redo相对,当对数据执行修改时,数据库会生成undo信息,如果事务失败了,希望ROLLBACK, 就可以利用undo信息来帮助完成恢复到之前的样子。与redo不同,undo在数据库内部存储在一组特殊的段中,称为undo段。针对undo,数据库只是逻辑地恢复到原来的样子,所有修改都被逻辑的取消,但是数据结构以及数据库块本身在回滚后可能大不相同。
SCN是Oracle的使用的一种简单的计时机制,用于保证事务的顺序,并支持失败恢复。SCN还用于保证数据库中的读一致性和检查点。可以把SCN看作一个钟摆,每次有人COMMIT时,SCN都会增1。
有些SQL语句和操作支持使用NOLOGGING子句,这并不是说:这个对象的所有操作都在执行时不生成重做日志,而是说有些特定操作生成的redo会比平常少得多。本质上,所有操作都会生成一个redo,不论日志模式是什么。
在一个ARCHIVELOG模式的数据库上,如果NOLOGGING使用得当,可以加快许多操作的速度:
1. 索引的创建和ALTER
2. 表的批量INSERT,表数据不生成redo,但是所有索引修改会生成redo
3. LOB操作(对大对象的更新不必生成日志)
4. 通过CREATETABLE AS SELECT创建表
5. 各种ALTERTABLE操作,如MOVE和SPLIT
常见导致日志竞争的原因:
1. Redo放在一个慢速设备上
2. Redo与其他频繁访问的文件放在同一个设备上
3. 以缓冲方式装载日志设备
4. Redo采用了一种慢速技术(RAID-5仅适合读)
(临时表不会为它们的块生成redo,但确实会生成undo。(不过由于undo本身也会造成一些redo生成))
Oracle数据表、索引
Oracle定义了9种表类型:
1. 堆组织表:普通的标准数据库表,以堆的方式来管理
2. 索引组织表:按照索引结构存储,强制要求行本身有某种物理顺序
3. 索引聚簇表:一个或者多个表组成的组,这些表物理地存储在相通的数据库块上
4. 散列聚簇表:类似于聚簇表但不使用B树索引来定位数据,在这里数据就是索引
5. 有序散列聚簇表:10g新增的
6. 嵌套表:系统生成和维护的父/子关系中的子表
7. 临时表:事务期间或会话的草稿数据
8. 对象表
9. 外部表:并不存储在数据库本身中,而是在数据库之外
Oracle的段是占用磁盘上存储空间的一个对象,尽管有多种段类型,最常见的类型如下:
1. 聚簇(cluster)
2. 表(table)
3. 表分区(table partition)
4. 索引(index)
5. 索引分区(index partition)
6. Lob分区(lob partition)
7. 嵌套表(nested tale)
8. 回滚段(rollback)
应用中99%的情况下使用的可能都是堆组织表,随着IOT的出现,以后可能会有所改观,因为IOT本身就可以加索引。如果需要任何其他表类型,需在CREATE语句本身中指定。
Oracle包括的索引有:
1. B*树索引:例如降序索引、反向键索引、索引组织表等
2. 位图索引:适用于高度重复且只读的数据
3. 位图联结索引
4. 基于函数的索引
5. 应用域索引