2012年8月30日木曜日

[备份恢复] RMAN 配置

1. 重置配置
configure retention policy clear;

2. 备份策略
# 每个文件的备份需要保留天数或份数
configure retention policy to recovery window of n days;
configure retention policy to redundancy n;
configure retention policy to none;

3. 备份优化
configure backup optimization on;
configure backup optimization off;

4. IO 设备类型
configure default device type to disk;
configure default device type to sbt;
configure device type disk parallelism 2 backup type to backupset;

5. 控制文件自动备份
configure controlfile autobackup on;
configure controlfile autobackup off;
configure controlfile autobackup format for device type disk to '%F';
configure snapshot controlfile name to '/tmp/snapcf_fsdb.f'

6. 备份冗余
configure datafile backup copies for device type disk to 2;
configure archivelog backup copies for device type disk to 2;

7. 备份集大小
configure maxsetsize to unlimited;
configure maxsetsize to 100M;

8. 备份加密
configure encryption for database on;
configure encryption for tablespace users on;
configure encryption algorithm 'aes128';

9. 删除归档
configure archivelog deletion policy to none;
configure archivelog deletion policy to applied on standby;

[安装配置] Linux 卸载 Oracle10G

1. $ORACLE_HOME/bin/localconfig delete
2. rm -rf $ORACLE_BASE/*
3. rm -f /etc/oraInst.loc /etc/oratab
4. rm -rf /etc/oracle
5. rm -f /etc/inittab.cssd
6. rm -f /usr/local/bin/coraenv /usr/local/bin/dbhome /usr/local/bin/oraenv
7. userdel oracle; groupdel dba; groupdel oinstall
8. 删除数据文件, 环境变量设置

2012年8月24日金曜日

[备份恢复] 同时丢失控制文件与数据文件的恢复

1. 准备工作
1-1. 备份控制文件, 需要在创建表空间之前备份
SQL> alter database backup controlfile to '/tmp/control01.ctl';

1-2. 创建测试表空间
SQL> create tablespace tbs datafile '/data/asmdb/tbs01.dbf' size 5m;

1-3. 删除控制文件与测试数据文件


2. 恢复

2-1. 复制回备份控制文件, 并启动到 mount
SQL> startup mount

2-2. 利用 redo 恢复控制文件到最新
# 恢复后, 控制文件就有了删除丢失的数据文件的信息

SQL> recover database using backup controlfile;
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
/data/asmdb/redo01.log
ORA-00283: recovery session canceled due to errors
ORA-01244: unnamed datafile(s) added to control file by media recovery
ORA-01110: data file 5: '/data/asmdb/tbs01.dbf'
ORA-01112: media recovery not started

SQL> select * from v$tablespace;
       TS# NAME   INC BIG FLA ENC
---------- ------ --- --- --- ---
         7 TBS    YES NO  YES

SQL> select name from v$datafile;

NAME
--------------------------------------------
/oracle/product/10.2.0/db_1/dbs/UNNAMED00005

2-3. 手动创建丢失的数据文件, 并再次执行恢复
SQL> alter database create datafile 5 as '/data/asmdb/tbs01.dbf' size 5m;

SQL> recover database using backup controlfile;
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
/data/asmdb/redo01.log
Log applied.
Media recovery complete.

2-4. resetlogs 打开数据库, 查看恢复结果
SQL> alter database open resetlogs;

Database altered.

SQL> select * from tt;

        ID
----------
         1

2012年8月21日火曜日

[数据迁移] 数据库从文件系统迁移到 ASM 存储

前提条件: 磁盘组 DG1 DG2 均以创建并挂载

1. 确认所要迁移的文件
SQL>
select name from v$controlfile
union all
select name from v$datafile
union all
select name from v$tempfile
union all
select member from v$logfile
union all
select value from v$parameter where name = 'spfile';


2. 修改参数文件

2-1. control_files
SQL> alter system set control_files='+DG1' scope=spfile;

2-2. db_create_file_dest
SQL> alter system set db_create_file_dest='+DG1';

2-3. db_recovery_file_dest
SQL> alter system set db_recovery_file_dest='+DG2';


3. 迁移文件

3-1. 参数文件
SQL> create pfile from spfile;
SQL> create spfile='+DG1/asmdb/spfileasmdb.ora' from pfile;
SQL> shutdown immediate
$ mv initasmdb.ora initasmdb.ora.bak
$ cp initasmdb.ora.bak initasmdb.ora
$ vim initasmdb.ora
spfile='+DG1/asmdb/spfileasmdb.ora'

3-2. 控制文件
$ rman target /
RMAN> startup nomount
RMAN> restore controlfile from '/data/control01.ctl';
RMAN> alter database mount;

3-3. 数据文件
RMAN> backup as copy database format '+DG1';

RMAN> switch database to copy;
RMAN> recover database;
RMAN> alter database open;

3-4. 临时文件
SQL> select name,status,enabled from v$tempfile;
SQL> alter tablespace temp add tempfile '+DG1';
SQL> alter tablespace temp drop tempfile '/data/temp01.dbf';

3-5. 日志文件
SQL> alter database add logfile member '+DG1' to group 1;
SQL> alter database add logfile member '+DG1' to group 2;
SQL> alter database add logfile member '+DG1' to group 3;
SQL> alter system switch logfile;
SQL> alter database drop logfile member '/data/asmdb/redo01.log';
SQL> alter database drop logfile member '/data/asmdb/redo02.log';
SQL> alter database drop logfile member '/data/asmdb/redo03.log';


4. 查看迁移结果
SQL> shutdown immediate
SQL> startup
SQL>
select name from v$datafile
union all
select name from v$tempfile
union all
select name from v$controlfile
union all
select member from v$logfile;
union all
select value from v$parameter where name = 'spfile';

2012年8月20日月曜日

[数据迁移] 数据库从 ASM 存储迁移到文件系统

1. 确认所要修改的文件的位置
SQL>
select name from v$controlfile
union all
select name from v$datafile
union all
select name from v$tempfile
union all
select member from v$logfile
union all
select value from v$parameter where name = 'spfile';


2. 修改参数文件

2-1. control_files
SQL> alter system set control_files='/data/control01.ctl' scope=spfile;

2-1. db_create_file_dest
SQL> alter system set db_create_file_dest='';

2-2. db_recovery_file_dest
SQL> alter system set db_recovery_file_dest='/backup';

2-3. db_create_online_log_dest


3. 迁移

3-1. 参数文件
SQL> create pfile from spfile;
SQL> create spfile from pfile;

3-2. 拷贝控制文件
$ rman target /
RMAN> startup nomount
RMAN> restore controlfile from '+DG1/asmdb/controlfile/current.256.791556801';

3-3. 数据文件
RMAN> copy datafile '+DG1/asmdb/datafile/system.260.791556937' to '/data/system01.dbf';
RMAN> copy datafile '+DG1/asmdb/datafile/undotbs1.261.791556989' to '/data/undotbs01.dbf';
RMAN> copy datafile '+DG1/asmdb/datafile/sysaux.262.791556993' to '/data/sysaux01.dbf';
RMAN> copy datafile '+DG1/asmdb/datafile/users.264.791557029' to '/data/users01.dbf';

RMAN> alter database mount;
RMAN> switch database to copy;
RMAN> recover database;
RMAN> alter database open;

3-4. 临时文件
SQL> create temporary tablespace temp tempfile '/data/temp01.dbf' size 20m;
SQL> alter tablespace temp drop tempfile '+DG1/asmdb/datafile/temp.260.791556937';

3-5. 日志文件
SQL> select member from v$logfile;
SQL> alter database add logfile member '/data/redo01.log' to group 1;
SQL> alter database add logfile member '/data/redo02.log' to group 2;
SQL> alter database add logfile member '/data/redo03.log' to group 3;
SQL> alter database drop logfile member '+DG1/asmdb/onlinelog/group_1.257.791556811';
SQL> alter database drop logfile member '+DG1/asmdb/onlinelog/group_2.258.791556849';
SQL> alter database drop logfile member '+DG1/asmdb/onlinelog/group_3.259.791556889';

4. 查看迁移结果
SQL> shutdown immediate
SQL> startup
SQL>
select name from v$datafile
union all
select name from v$tempfile
union all
select name from v$controlfile
union all
select member from v$logfile
union all
select value from v$parameter where name = 'spfile';

2012年8月18日土曜日

[ASM] 单机环境配置 ASM 实例


1. 创建 CSS 服务

1-1. 添加 CSS 服务并启动
# /oracle/product/10.2.0/db_1/bin/localconfig add

1-2. 如果不能自动启动, 手动启动
# /etc/init.d/init.cssd run &
# /oracle/product/10.2.0/db_1/bin/crsctl start crs

1-3. 查看 CSS 是否已启动
# /oracle/product/10.2.0/db_1/bin/crsctl check crs
# ps auxwww|grep css


2. ASM 磁盘文件

2-1. 创建磁盘文件并挂载
# dd if=/dev/zero of=/data/asmdisks/asm01 bs=1k count=1000000
# losetup /dev/loop1 /data/asmdisks/asm01; sleep 2
# raw /dev/raw/raw1 /dev/loop1; sleep 2
# chown oracle:dba /dev/raw/raw1
# chmod 660 /dev/raw/raw1

2-2. 设置系统启动时自动挂载磁盘文件
# cat /etc/init.d/dbora
--
#!/bin/sh
#chkconfig: 2345 99 01

losetup /dev/loop1 /data/asmdisks/asm01; sleep 2

raw /dev/raw/raw1 /dev/loop1; sleep 2

chown oracle:dba /dev/raw/raw1

chmod 660 /dev/raw/raw1
--

3. 创建 ASM 实例
# dbca

[ASM] ASM 相关操作


1. asm 相关初始化参数

1-1. parameter db_unique_name, 可通过 alter 命令修改
> show parameter db_unique_name
name           type   value
-------------- ------ -----
db_unique_name string +asm

1-2. instance_type
> show parameter instance_type
name          type   value
------------- ------ -----
instance_type string asm

1-3. asm_power_limit, 1 - 11, 默认是 1, 指定 rebalance 消耗资源等级
> show parameter asm_power_limit
name            type    value
--------------- ------- -----
asm_power_limit integer 1

1-4. asm_diskgroups, asm 启动时或 all mount 时自动挂载的磁盘组
> show parameter asm_diskgroups
name           type   value
-------------- ------ --------
asm_diskgroups string dg2, dg1

> alter system set asm_diskgroups='' sid='*';
> alter system set asm_diskgroups=dg1,dg2,dg3 sid='*';

1-5. asm_diskstring, 默认是 null, 所有 asm 拥有读写权限的磁盘
> show parameter asm_diskstring
name           type   value
-------------- ------ -------------
asm_diskstring string /dev/raw/raw*

1-6. db_create_file_dest
# 对于数据库实例 (类型是 RDBMS) 有效
# 指定 OMF 自动创建文件名的磁盘组, 创建是可以不指定磁盘组

> alter system set db_create_file_dest='DG1';

2. asm 相关操作
export oracle_sid=+asm
sqlplus / as sysdba

2-1. 创建磁盘组, force 可以将磁盘从其他组移动到这一组
create diskgroup dg1 normal redundancy
  failgroup fg1 disk
    '/dev/raw/raw1' name disk01,
    '/dev/raw/raw2' name disk02
  failgroup fg2 disk
    '/dev/raw/raw3' name disk03,
    '/dev/raw/raw4' name disk04;

create diskgroup dg2 external redundancy disk '/dev/raw/raw5','/dev/raw/raw6';

2-2. 删除磁盘组
drop diskgroup dg1 including contents;

2-3. 增加/删除磁盘
alter diskgroup dg1 add disk '/asmdisks/asm*1', '/asmdisks/asm*2';
alter diskgroup dg1 add disk '/asmdisks/asm[123]' rebalance wait;
alter diskgroup dg1 drop disk disk01 rebalance wait;
alter diskgroup dg1 undrop disks;

2-4. 改变磁盘大小
alter diskgroup dg1 resize disk disk01 size 100g;
alter diskgroup dg1 resize disks in failgroup fg1 size 100g;
alter diskgroup dg1 resize all size 100g;

2-5. rebalance 磁盘组
alter diskgroup dg1 rebalance power 5 [wait];

2-6. 查看后台正在进行的操作
select * from v$asm_operation;

2-7. 挂载/卸载磁盘组
alter diskgroup all dismount;
alter diskgroup all mount;
alter diskgroup dg1 dismount;
alter diskgroup dg1 mount;

2-8. 创建/修改/删除模板
alter diskgroup dg1 add template template1 attributes (mirror fine);
alter diskgroup dg1 alter template template1 attributes (coarse);
alter diskgroup dg1 drop template template1;

unprotected 
mirror 
coarse 
fine 

2-9. 创建/重命名/删除目录
alter diskgroup dg1 add directory '+dg1/dir1';
alter diskgroup dg1 rename directory '+dg1/dir1' to '+dg1/dir_2';
alter diskgroup dg1 drop directory '+dg1/dir_2' force;

2-10. 创建/重命名/删除别名
alter diskgroup dg1 add alias '+dg1/dir/file.dbf' for '+dg1/asmdb/datafile/ts.342.3';
alter diskgroup dg1 add alias '+dg1/dir/file.dbf' for '+dg1.342.3';
alter diskgroup dg1 rename alias '+dg1/dir/file.dbf' to '+dg1/dir/file2.dbf';
alter diskgroup dg1 delete alias '+dg1/dir/file.dbf';

2-11. 删除文件
alter diskgroup dg1 drop file '+dg1/dir/file.dbf';
alter diskgroup dg1 drop file '+dg1.342.3';
alter diskgroup dg1 drop file '+dg1/asmdb/datafile/ts.342.3';

2-12. 检查元数据
alter diskgroup dg1 check file '+dg1/dir/file.dbf'
alter diskgroup disk_group_1 check failgroup failure_group_1;
alter diskgroup dg1 check disk disk01;
alter diskgroup dg1 check all;

3. 相关视图
select * from dict where table_name like 'V$ASM_%';

[ASM] 远程连接 ASM 实例


1. 创建 ASM 实例密码文件
$ORACLE_HOME/dbs/orapw+ASM

2. 查看初始化参数
show parameter remote_login_passwordfile

NAME                       TYPE    VALUE
-------------------------- ------- ------
remote_login_passwordfile  string  SHARED

3. 配置 ASM 实例静态监听
$ORACLE_HOME/network/admin/listener.ora
--
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = /oracle/product/10.2.0/db_1)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (SID_NAME = +ASM)
      (ORACLE_HOME = /oracle/product/10.2.0/db_1)
    )
  )

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
    )
  )
--

4. 配置客户端 tnsnames.ora
$ORACLE_HOME/network/admin/tnsnames.ora
--
asm =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 100.100.100.101)(PORT = 1521))
    )
    (CONNECT_DATA =
      (server = dedicated)
      (sid = +asm)
      (ur=a)
    )
  )
--

2012年8月17日金曜日

[LINUX 基础] CentOS 6.x 命令行 Ctrl+C 时输出 ^C 的问题

Linux 升级到 CentOS 6.x, OEL 6.x 等系统后, Terminal 中使用 Ctrl+C 时会输出 ^C, 比较讨厌
此时, 可以在终端输入 stty -echoctl 来设置其不显示 (stty echoctl 时恢复显示)

2012年8月14日火曜日

[基础知识] 对表列的操作

1. 增加列
1-1. 增加列
alter table t add col1 int;
alter table t add (col1 int, col2 varchar2(10));

1-2. 增加列时设置约束
# 此处增加的默认值会修改已存在数据行中的此列的值
alter table t add (col1 int, col2 varchar2(10) default 'dummy' not null);

2. 修改列

2-1. 修改列
alter table t modify col1 varchar2(10);
alter table t modify (col1 varchar2(10), col2 int);

2-2. 修改列时设置约束
alter table t modify (col1 varchar2(10), col2 int default 1);

2-3. 修改列时删除默认值约束
# 此处修改的默认值不会修改已存在数据行中的此列的值
alter table t modify col1 varchar2(10) default null);

2-4. 修改列名
alter table t rename column col1 to col2;

3. 删除列

3-1. 删除列
# 不能删除 sys 用户表的列, 大表需要较长时间
alter table t drop col1;
alter table t drop (col1,col2);

# 选项???
cascade constraint invalidate

4. 无效化/隐藏列
# 速度快, 立即返回, 无法恢复
alter table t set unused column col1 cascade constraints;

select owner,table_name,column_name,hidden_column from dba_tab_cols where table_name = 'T';

# 大表需要较长时间
alter table scott.t drop unused columns;

2012年8月13日月曜日

[基础知识] UNDO 相关查询

1. undo 相关视图
dba_rollback_segs
dba_undo_extents
v$transaction
v$rollstat
v$rollname
v$undostat
x$ktuxe

2. 查看 undo 相关参数
select name,value,issys_modifiable from v$parameter where name like '%undo%';
show parameter undo

3. 查看所有 undo 表空间与数据文件
select tablespace_name,status,retention from dba_tablespaces where contents='UNDO';
select file_name,bytes from dba_data_files where tablespace_name like '%UNDO%';

4. 查看所有回滚段/区/块信息及状态信息
select * from v$rollname;
select owner,segment_name,tablespace_name from dba_rollback_segs;
select usn,xacts,rssize,hwmsize,shrinks from v$rollstat order by usn;
select extent_id,bytes,status from dba_undo_extents where segment_name='_SYSSMU1$';
select segment_name,tablespace_name,extent_id,file_id,block_id,blocks from dba_extents where segment_name='_SYSSMU1$';
select segment_name,blocks,extents from dba_segments where segment_name='_SYSSMU1$';
select a.name,b.xacts,b.writes,b.extents from v$rollname a,v$rollstat b where a.usn=b.usn;

5. 查看事务对应的回滚信息
select xid,xidusn,xidslot,xidsqn,ubafil,ubablk from v$transaction;

Transaction ID (XID) = Undo segment No. + Slot No. + Sequence No.
undo 段头块的 trace 文件中和数据字典中均以 16 进制形式出现

事务表信息
select xid,xidusn,xidslot,xidsqn from v$transaction;
XID                  XIDUSN    XIDSLOT     XIDSQN
---------------- ---------- ---------- ----------
050022005A010000          5         34        346

转换规则
1. 050022005A010000 = 0500.2200.5A010000
2. 再做高低位互换,0500 => 0005, 2200 => 0022, 5A010000 => 0000015A
3. 获得XID = 0005.0022.0000015A, 这跟 undo header block 中记录的 xid 就完全一样

通过 sql 转换
select
    to_number(substr(xid,3,2)||substr(xid, 1,2),'xxxxxxxxxxxx') xidusn,
    to_number(substr(xid,7,2)||substr(xid, 5,2),'xxxxxxxxxxxx') xidslot,

    to_number(substr(xid,15,2)||substr(xid,13,2)||substr(xid,11,2)||substr(xid,9,2),'xxxxxxxxxxxx') xidsqn
from (select '050022005A010000' xid from dual);

6. 查看事务表信息
select indx,ktuxesta,ktuxecfl,ktuxesqn wrap#,ktuxescnw scnw,ktuxescnb scnb,ktuxerdbf dba_file,ktuxerdbb dba_block,ktuxesiz nub from x$ktuxe where ktuxeusn = 9 and ktuxeslt <= 5;

7. 查看/转储回滚段块
select header_block,header_file from dba_segments where segment_name='_SYSSMU1$';
alter system dump undo header '_SYSSMU1$';
alter system dump datafile 5 block 4308;
select spid from v$process where addr in (select paddr from v$session where sid=(select sid from v$mystat where rownum=1));

8. 查看哪个用户正在使用回滚段的资源
select s.username,u.name from v$transaction t,v$rollstat r,v$rollname u,v$session s where s.taddr=t.addr and t.xidusn=r.usn and r.usn=u.usn order by s.username;
select a.username, b.name, c.used_ublk from v$session a, v$rollname b, v$transaction c where a.saddr=c.ses_addr and b.usn=c.xidusn and a.username='SYS';

9. 查看 UNDO 表空间统计信息
# 10 分钟自动收集一次
select to_char(begin_time,'hh24:mi:ss') begin_time,to_char(end_time,'hh24:mi:ss') end_time,undoblks from v$undostat;

10. 设置 guarantee
alter tablespace undotbs1 retention guarantee;
alter tablespace undotbs1 retention noguarantee;
select tablespace_name,retention from dba_tablespaces where contents='UNDO';

11. 查看 IMU 信息
select * from v$sysstat where name like '%IMU%';

[基础知识] 对表进行碎片整理

1. move
表移动后相关索引和统计信息会失效, 需要重创建或收集

1-1. 普通 heap 表
# 生成新数据段, 块内数据重新配置, data_object_id 会发生改变
alter table t move [ pctfree | pctused | initrans ] [tablespace ts_name];

1-2. 索引组织表 (IOT)
alter table t move online;

1-3. 分区表
1-3-1. 分区单位的移动
alter table t move partition t_partition;

1-3-2. 子分区单位的移动
# 存在子分区时, 3-1 的分区移动会报 ORA-14257 错误
alter table t move subpartition t_subpartition;

2012年8月10日金曜日

[C 语言] glib 程序的编译

#include <stdio.h>
#include <stdlib.h>
#include <glib.h>

/* gcc `pkg-config --cflags --libs glib-2.0` aaa.c -o aaa */

int main()
{
    puts("hello");
    return 0;
}

2012年8月8日水曜日

[基础知识] 锁相关

1. 锁类型
latch锁: 保护内存结构, chain, 链
lock 锁: 保护 buffer, block | 排他锁 (X), 共享锁 (S)

2. 行级锁
由 DML 语句产生, 数据行的所标记指向事务槽

3. 事务锁 (TX)
一个事务修改多行也之会产生一个事务锁
由行级锁产生, commit 或 rollback 解锁, 不影响读 (产生 CR 块)

4. 表级锁 (TM)
即行级排他锁 RX 锁 (Row exclusive)
当进行 DML 时, 会自动在被更新的表上添加 RX 锁, 也可以执行 lock 命令显式的在表上添加 RX 锁
允许其他事务通过 DML 语句修改相同表里的其他数据行
允许其他事务使用 lock 命令对表添加 RX 锁定
不允许其他事务对表添加 X 锁

4-1. 行级共享锁 (Row Shared, 简称 RS 锁)
select * from t for update

4-2. 共享锁 (Share, 简称 S 锁)
lock table t in share mode

4-3. 排他锁 (Exclusive, 简称 X 锁)
lock table t in exclusive mode

4-4. 共享行级排他锁 (Share Row Exclusive, 简称 SRX 锁)
lock table t in share row exclusive mode

5. 视图
5-1. v$transaction
select xid,xidusn,xidslot,xidsqn,ubafil,ubablk,status from v$transaction;

xid: 事务ID
xidusn: 表示当前事务使用的回滚段的编号xidslot: 说明该事务在回滚段头部的事务表中对应的记录编号(也可以叫做槽号) 
xidsqn: 说明序列号
status: 说明该事务是否为活动的
ubafil: 该事务对应的最后(新)的回滚块数据文件
ubablk: 该事务对应的最后(新)的回滚块号

5-2. v$lock
记录了会话已经获得的锁定以及正在请求的锁定的信息
SID: 会话的ID号
TYPE: 锁定锁定级别
LMODE: 已经获得的锁定的模式, 以数字编码表示
REQUEST: 正在请求的锁定的模式, 以数字编码表示
BLOCK: 是否阻止了其他用户获得锁定, 大于 0 说明是, 等于 0 说明否

锁定模式                锁定简称 编码数值
Row Exclusive           RX       3
Row Shared              RS       2
Share                   S        4
Exclusive               X        6
Share Row Exclusive     SRX      5
NULL                    N/A      0 或者 1

select sid,type,id1,id2,
decode(lmode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_mode,
decode(request,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') request_mode,
block
from v$lock where sid=159;

获取锁定与被锁定的会话
select
    (select username from v$session where sid=a.sid) blocker,a.sid,' is blocking ',
    (select username from v$session where sid=b.sid) blockee,b.sid
from v$lock a,v$lock b
where a.block = 1 and b.request > 0 and a.id1 = b.id1 and a.id2 = b.id2;

对于 TM 锁来说, ID1 表示被锁定的对象的对象ID, ID2 始终为 0
对于 TX 锁来说, ID1 表示事务使用的回滚段编号以及在事务表中对应的记录编号, ID2 表示该记录编号被重用的次数
将 ID1 拆解
select trunc(393249/power(2,16)) as undo_blk#,bitand(393249,to_number('ffff','xxxx')) + 0 as slot# from dual;

5-3. v$enqueue_lock
该视图中包含的字段以及字段含义与 v$lock 中的字段一模一样
该视图中只显示那些申请锁定, 但是无法获得锁定的会话信息
记录按照申请锁定的时间先后顺序排列, 先申请锁定的会排在前面, 排在前面的会话将会先获得锁定

select a.sid blocker_sid,a.serial#,a.username as blocker_username,b.type,
decode(b.lmode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_mode,
b.ctime as time_held,c.sid as waiter_sid,
decode(c.request,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') request_mode,
c.ctime time_waited
from v$lock b, v$enqueue_lock c, v$session a
where a.sid = b.sid and b.id1= c.id1(+) and b.id2 = c.id2(+) and c.type(+) = 'TX' and  b.type = 'TX' and b.block = 1
order by time_held, time_waited;

alter system kill session '129,10910';

5-4. v$locked_object
记录了当前已经被锁定的对象的信息
XIDUSN: 当前事务使用的回滚段的编号
XIDSLOT: 该事务在回滚段头部的事务表中对应的记录编号
XIDSQN: 序列号
OBJECT_ID: 当前被锁定的对象ID, 可以根据该 ID 号到 dba_objects 里查找被锁定的对象名称
LOCKED_MODE: 锁定模式的数字编码

select /*+ RULE */ /* ls.osuser os_user_name,*/ ls.username,ls.type,o.object_name,
decode(ls.lmode,1,null,2, 'Row Share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive',null) lock_mode,
o.owner,ls.sid,ls.serial#,ls.id1,ls.id2
from dba_objects o,
(select s.osuser,s.username,l.type,l.lmode,s.sid,s.serial#,l.id1,l.id2 from v$session s,v$lock l where s.sid = l.sid) ls
where o.object_id = ls.id1 /* and o.owner <> 'SYS' */
order by o.owner, o.object_name;

5-5. v$session
记录了当前所有会话的相关信息
SID: 会话的编号
SERIAL#: 序列号
SID 和 SERIAL# 可以认为是 v$session 的主键, 它们共同唯一标识一个会话

6. 初始化参数
transactions: 数据库整体能执行的并行活动事务总数 (可以获得的 TX 锁定的总个数)
dml_locks: 一个表上可以同时获得的 TM 锁总数
select name,value,description from v$parameter where name in('transactions','dml_locks');

select resource_name,current_utilization,max_utilization,initial_allocation
from v$resource_limit
where resource_name in('transactions','dml_locks');

7. 死锁
在 Oracle中, 造成死锁的那个 DML 语句会被撤销, 死锁总是由于应用程序设计不合理引起的
当某个会话的事务引起了死锁时, Oracle 会自动将阻塞该事务的其他事务中相应的 DML 语句撤销, 而阻塞该事务的其他事务中的其他 DML 语句并没有撤销

session 1
--
select sid from v$mystat where rownum=1;
update employees set last_name=last_name||'a'
where employee_id=100

session 2
--
select sid from v$mystat where rownum=1;
update employees set last_name=last_name||'b'
where employee_id=101;

session 1
--
update employees set last_name=last_name||'c' where employee_id=101;

session 2
--
update employees set last_name=last_name||'d' where employee_id=100;



[基础知识] PGA 相关

1. PGA 构成
private SQL area
Session Memory
SQL Work Areas

2. 重要参数

2-1. pga_aggregate_target (PGA 自动管理分配的总计内存的大小, 不够时 oracle 自动申请额外内存)
在 OLTP 系统中, 典型 PGA 内存设置应该是总内存的较小部分(20%), 剩下 80% 分配给 SGA
OLTP: PGA_AGGREGATE_TARGET = (total_mem * 80%) * 20%
在 DSS 系统中, 由于会运行一些很大的查询, 典型的 PGA 内存最多分配 70% 的内存
DSS: PGA_AGGREGATE_TARGET = (total_mem * 80%) * 50%

alter system set pga_aggregate_target=512m scope=both;

2-2. workarea_size_policy (PGA 自动管理)
alter system set workarea_size_policy=auto scope=both;
alter system set workarea_size_policy=manual scope=both;

2-3. _pga_max_size
select ksppinm "Name", ksppstvl/1024/1024||'M' "Value", ksppdesc "Desc"
from x$ksppi x, x$ksppcv y
where x.indx = y.indx and ksppinm ='_pga_max_size';

2-4. 其他参数
# 某些参数是 PGA 手动管理时需要设置的
sort_area_size
sort_area_retained_size
hash_area_size
hash_join_enable
bitmap_merge_area_size
create_bitmap_area_size
open_cursors

3. 重要视图
3-1. 查看当前 PGA 状态
select * from v$pgastat;

3-2. PGA 指导
select
    pga_target_for_estimate/1024/1024 ||'M' "Estimate PGA Target",
    estd_pga_cache_hit_percentage "Cache Hit(%)",
    estd_extra_bytes_rw/1024/1024 ||'M' "Extra Read/Write",
    estd_overalloc_count "Over alloc count"
from v$pga_target_advice;

3-3. 查看 数据库启动以来的排序情况
select * from V$SYSSTAT where name like '%sort%';

3-4. 
获得引发排序的语句
SELECT /*+ rule */ DISTINCT a.SID,a.process,a.serial#,TO_CHAR (a.logon_time, 'YYYYMMDD HH24:MI:SS') LOGON,a.osuser,TABLESPACE,b.sql_text FROM v$session a,v$sql b,v$sort_usage c WHERE a.sql_address=b.address(+) AND a.sql_address=c.sqladdr;

3-5. 查看当前/所有会话 PGA 使用情况
select name,value from v$statname a,v$mystat b where a.statistic#=b.statistic# and a.name like '%pga%';

select spid,program,pga_max_mem,pga_alloc_mem,pga_used_mem,pga_freeable_mem
from v$process
where spid in (select spid from v$process where addr in (select paddr from v$session where sid in (select distinct sid from v$mystat)));

select spid,program,pga_max_mem,pga_alloc_mem,pga_used_mem,pga_freeable_mem from v$process where PROGRAM like '%oracle%'

3-6. 查看当前/所有会话 PGA 各个区域使用情况
select p.PROGRAM,p.SPID,pm.CATEGORY,pm.ALLOCATED,pm.USED,pm.MAX_ALLOCATED
from v$process p,v$process_memory pm
where p.PID=pm.PID and p.SPID in (select spid from v$process where addr in (select paddr from v$session where sid in (select distinct sid from v$mystat )));

2012年8月7日火曜日

[基础知识] BUFFER CACHE 相关

1. 查看当前 SGA 动态分配的大小
select component,current_size,min_size from v$sga_dynamic_components;

2. 修改 buffer cache 大小
alter system set db_cache_size=200M scope=both;

3. 指导
DB_CACHE_SIZE = SGA_MAX_SIZE/2~ SGA_MAX_SIZE*2/3
select
    size_for_estimate "Cache Size (MB)",
    size_factor,
    buffers_for_estimate "Buffers",
    estd_physical_read_factor est_read_factor,
    estd_physical_reads estd_phy_red,
    estd_physical_read_time est_phy_red_t
from v$db_cache_advice
where name='DEFAULT' and block_size=(select value from v$parameter where name='db_block_size');

4. 一个对象占用 BUFFER 的具体情况
select
    o.object_name,
    decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',6,'irec',7,'write',8,'pi') state,
    count(*) blocks
from x$bh b,dba_objects o
where b.obj=o.data_object_id and o.object_name='T'
group by o.object_name, state order by blocks asc;

select object_name,DBARFIL,DBABLK from x$bh a,dba_objects b where a.obj=b.object_id and object_name='T';

5. 对象使用各个池的情况
select
    decode(wbpd.bp_id,1,'keep',2,'recycle',3,'default',4,'2k pool',5,'4k pool',6,'8k pool',7,'16k pool',8,'32k pool','unknown') pool,
    bh.owner,
    bh.object_name,
    count(1) numOfBuffers
from
    x$kcbwds wds,
    x$kcbwbpd wbpd,
    (
        select set_ds, x.addr, o.name object_name, u.name owner
        from sys.obj$ o, sys.user$ u, x$bh x
        where o.owner# = u.user#
            and o.dataobj# = x.obj
            and x.state != 0
            and o.owner# != 0
    ) bh
where
    wds.set_id >= wbpd.bp_lo_sid and
    wds.set_id <= wbpd.bp_hi_sid and
    wbpd.bp_size != 0 and
    wds.addr = bh.set_ds
group by
    decode(wbpd.bp_id,1,'keep',2,'recycle',3,'default',4,'2k pool',5,'4k pool',6,'8k pool',7,'16k pool',8,'32k pool','unknown'),
    bh.owner,
    bh.object_name
order by 1, 4, 3, 2;

6. 寻找热块
select obj,dbarfil,dbablk,tch from x$bh where tch > 10 order by tch asc;
select object_name,dbarfil,dbablk from x$bh a,dba_objects b where a.obj=b.object_id and dbarfil=1 and dbablk=338;

7. 整个数据库所有文件中总块数
select sum(blocks) from dba_data_files;

8. 空闲空间的比例, 最好控制在10%以内
select
    decode(state,0,'FREE',1,decode(lrba_seq,0,'AVAILABLE','BEING USED'),3,'BEING USED',state) "BLOCK STATUS",
    count(*)
from  x$bh
group by decode(state,0,'FREE',1,decode(lrba_seq,0,'AVAILABLE','BEING USED'),3, 'BEING USED', state);

9. buffer cache 具体使用情况
set linesize 200 pagesize 1400
select /*+ ordered use_hash(o u) merge */
    decode(obj#,null,to_char(bh.obj),u.name||'.'||o.name) name,
    count(*) total,
    sum(decode((decode(lru_flag,8,1,0)+decode(sign(tch-2),1,1,0)),2,1,1,1,0)) hot,
    sum(decode(decode(sign(lru_flag-8),1,0,0,0,1)+decode(tch,2,1,1,1,0,1,0),2,1,1,0,0)) cold,
    sum(decode(bitand(flag,power(2,19)),0,0,1)) fts,
    sum(tch) total_tch,
    round(avg(tch),2) avg_tch,
    max(tch) max_tch,
    min(tch) min_tch
from x$bh bh, sys.obj$ o, sys.user$ u
where
    bh.obj<>4294967295 and
    bh.state in (1,2,3) and
    bh.obj=o.dataobj#(+) and
    bh.inst_id=userenv('INSTANCE') and
    o.owner#=u.user#(+) and
    u.name not like 'AURORA$%'
    --and o.owner# > 5
group by decode(obj#,null,to_char(bh.obj),u.name||'.'||o.name)
order by total desc;

10. buffer cache中每一个对象的使用情况
select
    t.name as tablespace_name,
    o.object_name,
    sum(decode(bh.status,'free',1,0)) as free,
    sum(decode(bh.status,'xcur',1,0)) as xcur,
    sum(decode(bh.status,'scur',1,0)) as scur,
    sum(decode(bh.status,'cr',1,0)) as cr,
    sum(decode(bh.status,'read',1,0)) as read,
    sum(decode(bh.status,'mrec',1,0)) as mrec,
    sum(decode(bh.status,'irec',1,0)) as irec
from v$bh bh
join dba_objects o on o.data_object_id=bh.objd
join v$tablespace t on t.ts#=bh.ts#
group by t.name,o.object_name
order by xcur desc;

11. 命中率
11-1. 缓冲区总命中率
select 100*(p1.value+p2.value-p3.value)/(p1.value+p2.value) "Hit Ratio(%)"
from v$sysstat p1, v$sysstat p2, v$sysstat p3
where p1.name = 'db block gets' and p2.name = 'consistent gets' and p3.name = 'physical reads';

11-2. 指定 session 缓冲区命中率
select (p1.value+p2.value-p3.value)/(p1.value+p2.value)
from v$sesstat p1,v$statname n1,v$sesstat p2,v$statname n2,v$sesstat p3,v$statname n3
where
    n1.name='db block gets' and
    p1.statistic#=n1.statistic# and
    p1.sid=(select distinct sid from v$mystat) and
    n2.name='consistent gets' and
    p2.statistic#=n2.statistic# and
    p2.sid=p1.sid and
    n3.name='physical reads' and
    p3.statistic#=n3.statistic# and
    p3.sid=p1.sid;

12. 各数据文件在数据库启动后的访问情况
select a.file_name, b.phyrds, b.phyblkrd from sys.dba_data_files a, v$filestat b
where b.file# = a.file_id
order by a.file_id

13. 清空buffer cache
alter system flush buffer_cache;

2012年8月6日月曜日

[基础知识] SHARED POOL 相关

1. 查看共享池组成
select * from v$sgastat
where pool='shared pool' and name in ('free memory','library cache','row cache');

2. 刷新(清空)共享池
# 此后会发生大量硬解析
alter system flush shared_pool;

3. 查看软/硬解析的具体情况
select name,value from v$sysstat where name like 'parse%';

4. 查看共享池中缓存的 SQL 语句
select sql_id,sql_text,executions from v$sql;

5. 查看没有被共享的 SQL 语句
# 在 v$sql 查找执行次数较小的 SQL 语句, 观察这些 SQL 语句是否是经常被执行

select sql_fulltext from v$sql where executions=1 and sql_text like '%hello%';
select sql_fulltext from v$sql where executions=1 order by sql_text;

6. 查看共享池中 trunk 总数
select count(*) from x$ksmsp;

7. 查看命中率
7-1. 软解析命中率
select sum(pinhits)/sum(pins)*100 from v$librarycache;

7-2. 数据字典命中率
select sum(gets),sum(getmisses),100*sum(gets-getmisses)/sum(gets)
from v$rowcache where gets>0;

8. 查看 SGA 中动态分配的共享池大小
select component,current_size from V$sga_dynamic_components;

9. 修改共享池大小
# 数值必须大于 7 中动态分配的大小才有效

alter system set shared_pool_size=150M scope=both;

10. 根据 sql_id 查看执行计划
select * from table(dbms_xplan.display_cursor('g4pkmrqrgxg3b'));

11. 大对象
11-1. 查看内存中的大对象
select * from v$db_object_cache
where sharable_mem > 10000 and
(type = 'PACKAGE' or type='PACKAGE BODY' or type = 'FUNCTION' or type='PROCEDURE') and
kept = 'NO';

11-2. 保留大对象
# 在内存中保留大对象, 使其不容易被置换出内存
@?/rdbms/admin/dbmspool.sql
执行 dbms_shared_pool.keep('对象名');

11-3. 查看大对象保留区
show parameter shared_pool_reserved_size
select request_misses from v$shared_pool_reserved;

12. 查看最浪费内存的前10个 SQL 占所有语句的比例, 建议控制在5%以内
select sum(pct_bufgets) "Percent"
from
    (
        select
            rank() over (order by buffer_gets desc) as rank_bufgets,
            to_char(100 * ratio_to_report(buffer_gets) over (),'999.99') pct_bufgets
        from v$sqlarea
    )
where rank_bufgets < 11;

13. 查看消耗物理 IO 资源最大的的 SQL 语句
select disk_reads,substr(sql_text,1,4000) from v$sqlarea order by disk_reads asc;

14. 使用共享池大小设置指导
select
    shared_pool_size_for_estimate,
    estd_lc_size,estd_lc_memory_objects,
    estd_lc_time_saved,
    estd_lc_time_saved_factor,
    estd_lc_memory_object_hits
from v$shared_pool_advice;

select
    'Shared Pool' component,
    shared_pool_size_for_estimate,
    estd_lc_time_saved_factor,
    case
        when current_parse_time_elapsed_s + adjustment_s < 0
        then 0
        else current_parse_time_elapsed_s + adjustment_s
    end response_time
from
(
    select
        shared_pool_size_for_estimate,
        shared_pool_size_factor,
        estd_lc_time_saved_factor,
        a.estd_lc_time_saved,
        e.value/100 current_parse_time_elapsed_s,
        c.estd_lc_time_saved - a.estd_lc_time_saved adjustment_s
    from
        v$shared_pool_advice a,
        (select * from v$sysstat where name = 'parse time elapsed') e,
        (select estd_lc_time_saved from v$shared_pool_advice where shared_pool_size_factor = 1) c
);

2012年8月5日日曜日

[基础知识] 硬盘的“磁道、柱面、扇区、簇”

磁道、扇区和柱面

当磁盘旋转时,磁头若保持在一个位置上,则每个磁头都会在磁盘表面划出一个圆形轨迹,这些圆形轨迹就叫做磁道。下图是一张磁盘片与一个磁头的放大图(图中夸张地放大了磁头相对于磁盘的尺寸,因此,也放大了磁道的宽度)。
硬盘构造1

这些磁道用肉眼是根本看不到的,因为它们仅是盘面上以特殊方式磁化了的一些磁化区,磁盘上的信息便是沿着这样的轨道存放的。相邻磁道之间并不是紧挨着的, 这是因为磁化单元相隔太近时磁性会相互产生影响,同时也为磁头的读写带来困难。一张1.44MB的3.5英寸软盘,一面有80个磁道,而硬盘上的磁道密度 则远远大于此值,通常一面有成千上万个磁道。
磁盘上的每个磁道被等分为若干个弧段,这些弧段便是磁盘的扇区,每个扇区可以存放512个字节的信息,磁盘驱动器在向磁盘读取和写入数据时,要以扇区为单位。1.44MB3.5英寸的软盘,每个磁道分为18个扇区。
硬盘构造2

硬盘通常由重叠的一组盘片构成,每个盘面都被划分为数目相等的磁道,并从外缘的"0"开始编号,从上图这张放大的硬盘结构图我们可以看出,具有相同编号的磁道形成一个圆柱,称之为磁盘的柱面。磁盘的柱面数与一个盘面上的磁道数是相等的。由于每个盘面都有自己的磁头,因此,盘面数等于总的磁头数。所谓硬盘的CHS,即Cylinder(柱面)、Head(磁头)、Sector(扇区),只要知道了硬盘的CHS的数目,即可确定硬盘的容量,硬盘的容量=柱面数×磁头数×扇区数×512B。

硬盘的“磁道、柱面、扇区、簇”这些之间有什么关系

1. 硬盘最基本的组成部分是由坚硬金属材料制成的涂以磁性介质的盘片,不同容量硬盘的盘片数不等。每个盘片有两面,都可记录信息。盘片被分成许多扇形的区域, 每个区域叫一个扇区,每个扇区可存储128×2的N次方(N=0.1.2.3)字节信息。在DOS中每扇区是128×2的2次方=512字节,盘片表面上 以盘片中心为圆心,不同半径的同心圆称为磁道。硬盘中,不同盘片相同半径的磁道所组成的圆柱称为柱面。磁道与柱面都是表示不同半径的圆,在许多场合,磁道 和柱面可以互换使用,我们知道,每个磁盘有两个面,每个面都有一个磁头,习惯用磁头号来区分。扇区,磁道(或柱面)和磁头数构成了硬盘结构的基本参数,帮 这些参数可以得到硬盘的容量,基计算公式为:
存储容量=磁头数×磁道(柱面)数×每道扇区数×每扇区字节数

要点:(1)硬盘有数个盘片,每盘片两个面,每个面一个磁头
(2)盘片被划分为多个扇形区域即扇区
(3)同一盘片不同半径的同心圆为磁道
(4)不同盘片相同半径构成的圆柱面即柱面
(5)公式: 存储容量=磁头数×磁道(柱面)数×每道扇区数×每扇区字节数
(6)信息记录可表示为:××磁道(柱面),××磁头,××扇区
2. 簇
“簇”是DOS进行分配的最小单位。当创建一个很小的文件时,如是一个字节,则它在磁盘上并不是只占一个字节的空间,而是占有整个一簇。DOS 视不同的存储介质(如软盘,硬盘),不同容量的硬盘,簇的大小也不一样。簇的大小可在称为磁盘参数块(BPB)中获取。簇的概念仅适用于数据区。
要点:(1)“簇”是DOS进行分配的最小单位。
(2)不同的存储介质,不同容量的硬盘,不同的DOS版本,簇的大小也不一样。
(3)簇的概念仅适用于数据区。3. 扇区编号定义:绝对扇区与DOS扇区
由前面介绍可知,我们可以用柱面/磁头/扇区来唯一定位磁盘上每一个区域,或是说柱面/磁头/扇区与磁盘上每一个扇区有一一对应关系,通常DOS将“柱面 /磁头/扇区”这样表示法称为“绝对扇区”表示法。但DOS不能直接使用绝对扇区进行磁盘上的信息管理,而是用所谓“相对扇区”或“DOS扇区”。“相对 扇区”只是一个数字,如柱面140,磁头3,扇区4对应的相对扇区号为2757。该数字与绝对扇区“柱面/磁头/扇区”具有一一对应关系。当使用相对扇区 编号时,DOS是从柱面0,磁头1,扇区1开始(注:柱面0,磁头0,扇区1没有DOS扇区编号,DOS下不能访问,只能调用BIOS访问),第一个 DOS扇区编号为0,该磁道上剩余的扇区编号为1到16(设每磁道17个扇区),然后是磁头号为2,柱面为0的17个扇区,形成的DOS扇区号从17到 33。直到该柱面的所有磁头。然后再移到柱面1,磁头1,扇区1继续进行DOS扇区的编号,即按扇区号,磁头号,柱面号(磁道号)增长的顺序连续地分配 DOS扇区号。
公式:记DH--第一个DOS扇区的磁头号
DC--第一个DOS扇区的柱面号
DS--第一个DOS扇区的扇区号
NS--每磁道扇区数
NH--磁盘总的磁头数
则某扇区(柱面C,磁头H,扇区S)的相对扇区号RS为:
RS=NH×NS×(C-DC)+NS×(H-DH)+(S-DS)
若已知RS,DC,DH,DS,NS和NH则
S=(RS MOD NS)+DS
H=((RS DIV NS)MOD NH)+DH
C=((RS DIV NS)DIV NH)+DC
要点:(1)以柱面/磁头/扇区表示的为绝对扇区又称物理磁盘地址
(2)单一数字表示的为相对扇区或DOS扇区,又称逻辑扇区号
(3)相对扇区与绝对扇区的转换公式4. DOS磁盘区域的划分
格式化好的硬盘,整个磁盘按所记录数据的作用不同可分为主引导记录(MBR:Main Boot Record),Dos引导记录(DBR:Dos Boot Record),文件分配表(FAT:File Assign Table),根目录(BD:Boot Directory)和数据区。前5个重要信息在磁盘的外磁道上,原因是外圈周长总大于内圈周长,也即外圈存储密度要小些,可靠性高些。
要点:(1)整个硬盘可分为MBR,DBR,FAT,BD和数据区。
(2)MBR,DBR,FAT,和BD位于磁盘外道。5. MBR
MBR位于硬盘第一个物理扇区(绝对扇区)柱面0,磁头0,扇区1处。由于DOS是由柱面0,磁头1,扇区1开始,故MBR不属于DOS扇区,DOS不能 直接访问。MBR中包含硬盘的主引导程序和硬盘分区表。分区表有4个分区记录区。记录区就是记录有关分区信息的一张表。它从主引导记录偏移地址01BEH 处连续存放,每个分区记录区占16个字节。
分区表的格式
分区表项的偏移 意义 占用字节数
00 引导指示符 1B
01 分区引导记录的磁头号 1B
02 分区引导记录的扇区和柱面号 2B
04 系统指示符 1B
05 分区结束磁头号 1B
06 分区结束扇区和柱面号 2B
08 分区前面的扇区数 4B
0C 分区中总的扇区数 4B
4个分区中只能有1个活跃分区,即C盘。标志符是80H在分区表的第一个字节处。若是00H则表示非活跃分区。例如:
80 01 01 00 0B FE 3F 81 3F 00 00 00 C3 DD 1F 00
00 00 01 82 05 FE BF 0C 02 DE 1F 00 0E 90 61 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
要点:(1)MBR位于硬盘第一个物理扇区柱面0,磁头0,扇区1处。不属于DOS扇区,
(2)主引导记录分为硬盘的主引导程序和硬盘分区表。6. DBR
DBR位于柱面0,磁头1,扇区1,即逻辑扇区0。DBR分为两部分:DOS引导程序和BPB(BIOS参数块)。其中DOS引导程序完成DOS系统文件 (IO.SYS,MSDOS.SYS)的定位与装载,而BPB用来描述本DOS分区的磁盘信息,BPB位于DBR偏移0BH处,共13字节。它包含逻辑格 式化时使用的参数,可供DOS计算磁盘上的文件分配表,目录区和数据区的起始地址,BPB之后三个字提供物理格式化(低格)时采用的一些参数。引导程序或 设备驱动程序根据这些信息将磁盘逻辑地址(DOS扇区号)转换成物理地址(绝对扇区号)。BPB格式
序号 偏移地址 意义
1 03H-0AH OEM号
2 0BH-0CH 每扇区字节数
3 0DH 每簇扇区数
4 0EH-0FH 保留扇区数
5 10H FAT备份数
6 11H-12H 根目录项数
7 13H-14H 磁盘总扇区数
8 15H 描述介质
9 16H-17H 每FAT扇区数
10 18H-19H 每磁道扇区数
11 1AH-1BH 磁头数
12 1CH-1FH 特殊隐含扇区数
13 20H-23H 总扇区数
14 24H-25H 物理驱动器数
15 26H 扩展引导签证
16 27H-2AH 卷系列号
17 2BH-35H 卷标号
18 36H-3DH 文件系统号
DOS引导记录公式:
文件分配表≡保留扇区数
根目录≡保留扇区数+FAT的个数×每个FAT的扇区数
数据区≡根目录逻辑扇区号+(32×根目录中目录项数+(每扇区字节数-1))DIV每扇区字节数
绝对扇区号≡逻辑扇区号+隐含扇区数
扇区号≡(绝对扇区号MOD每磁道扇区数)+1
磁头号≡(绝对扇区号DIV每磁道扇区数)MOD磁头数
磁道号≡(绝对扇区号DIV每磁道扇区数)DIV磁头数
要点:(1)DBR位于柱面0,磁头1,扇区1,其逻辑扇区号为0
(2)DBR包含DOS引导程序和BPB。
(3)BPB十分重要,由此可算出逻辑地址与物理地址。
7. 文件分配表
文件分配表是DOS文件组织结构的主要组成部分。我们知道DOS进行分配的最基本单位是簇。文件分配表是反映硬盘上所有簇的使用情况,通过查文件分配表可 以得知任一簇的使用情况。DOS在给一个文件分配空间时总先扫描FAT,找到第一个可用簇,将该空间分配给文件,并将该簇的簇号填到目录的相应段内。即形 成了“簇号链”。FAT就是记录文件簇号的一张表。FAT的头两个域为保留域,对FAT12来说是3个字节,FAT来说是4个字节。其中头一个字节是用来 描述介质的,其余字节为FFH 。介质格式与BPB相同。
第一个字节的8位意义:
7 6 5 4 3 2 1 0
└—————-┘ │ │ │┌0非双面
置1 │ │ └┤
│ │ └1双面
│ │┌0不是8扇区
│ └┤
│ └1是8扇区
│┌0不是可换的
└┤
└1是可换的
FAT结构含义
FAT12 FAT16 意义
000H 0000H 可用
FF0H-FF6H FFF0H-FFF6H 保留
FF7H FFF7H 坏
FF8H-FFFH FFF8H-FFFFH 文件最后一个簇
×××H ××××H 文件下一个簇
对于FAT16,簇号×2作偏移地址,从FAT中取出一字即为FAT中的域。
逻辑扇区号=数据区起始逻辑扇区号+(簇号-2)×每簇扇区数
簇号=(逻辑扇区号-数据区起始逻辑扇区号)DIV每簇扇区数+2
要点:(1)FAT反映硬盘上所有簇的使用情况,它记录了文件在硬盘中具体位置(簇)。
(2)文件第一个簇号(在目录表中)和FAT的该文件的簇号串起来形成文件的“簇号链”,恢复被破坏的文件就是根
据这条链。
(3)由簇号可算逻辑扇区号,反之,由逻辑扇区号也可以算出簇号,公式如上。
(4)FAT位于DBR之后,其DOS扇区号从1开始。
8. 文件目录
文件目录是DOS文件组织结构的又一重要组成部分。文件目录分为两类:根目录,子目录。根目录有一个,子目录可以有多个。子目录下还可以有子目录,从而形 成“树状”的文件目录结构。子目录其实是一种特殊的文件,DOS为目录项分配32字节。目录项分为三类:文件,子目录(其内容是许多目录项),卷标(只能 在根目录,只有一个。目录项中有文件(或子目录,或卷标)的名字,扩展名,属性,生成或最后修改日期,时间,开始簇号,及文件大小。
目录项的格式
字节偏移 意义 占字节数
00H 文件名 8B
08H 扩展名 3B
0BH 文件属性 1B
0CH 保留 10B
16H 时间 2B
18H 日期 2B
1AH 开始簇号 2B
1CH 文件长度 4B
目录项文件名区域中第一个字节还有特殊的意义:00H代表未使用
05H代表实际名为E5H
EBH代表此文件已被删除
目录项属性区域的这个字节各个位的意义如下: 7 6 5 4 3 2 1 0
未 修 修 子 卷 系 隐 只
用 改 改 目 标 统 藏 读
标 标 录 属 属 属
志 志 性 性 性
注意:WINDOWS的长文件名使用了上表中所说的“保留”这片区域。
要点:(1)文件目录是记录所有文件,子目录名,扩展名属性,建立或删除最后修改日期。文件开始簇号及文件长度的一张
登记表.
(2)DOS中DIR列出的内容训是根据文件目录表得到的。
(3)文件起始簇号填在文件目录中,其余簇都填在FAT中上一簇的位置上。
9. 物理驱动器与逻辑驱动器
物理驱动器指实际安装的驱动器。
逻辑驱动器是对物理驱动器格式化后产生的。

==================================================================

1. 物理结构

1.1 磁头

硬盘是通过磁头的移动来传递信号的。通常一个盘片有两个磁头,一个硬盘有多个盘片。

1.2 磁道

磁头走的每个同心圆都是一个磁道

1.3 扇区

每个磁道分为多个扇区单元(每个扇区通常有 512B 的容量)

1.4 柱面

这是一个"虚拟"概念:所有盘片“同一位置”的磁道都在同一柱面。

2. 逻辑结构

2.1 CHS

早期的硬盘使用 Cylinder(柱面)、Head(磁头)、Sector(扇区) 来表示磁盘的位置。

2.1.1 3D 参数 (CHS)

MBR 中的分区表信息用 CHS 方法储存。
  • C ( Cylinder ) , (10 bit)
  • H ( Head ), (8 bit)
  • S ( Sector ), (6 bit)
  • 扇区大小, 一般为 512B
CHS 能表示的最大硬盘容量为: 255 * 1023 * 63 * 512 B ( 约为 8G )
最基本 BIOS int 13H 调用使用 CHS 寻址。

2.2 LBA (Logical Block Addressing)

为了表示大于 8G 的硬盘, LBA 是其中一种扩展方式。在 CHS 能表示的范围 内, LBA 地止可由 CHS 值计算出来:
LBA值 = 磁头总数 x 每磁道扇区数 x 柱面 + 每磁道扇区数 x 磁头 + (扇区 - 1)

3. 两个实际的分区信息

用 fdisk 工具的 x 模式中的 p 命令得到 /dev/sda 硬盘分区信息。

3.1 下面是我本子上的 250G 硬盘

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Disk /dev/sda: 255 heads, 63 sectors, 30401 cylinders

Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 80  32  33    0 129  33  162       2048    2455552 07
 2 00 129  34  162 239  63 1023    2457600   62914560 07
 3 00 239  63 1023 239  63 1023   65372160   61440000 07
 4 00 239  63 1023 239  63 1023  126814206  345700354 05
 5 00 239  63 1023 239  63 1023          2  234373120 83
 6 00 239  63 1023 239  63 1023       2048   70309888 83
 7 00 239  63 1023 239  63 1023       2048   35153920 83
 8 00 239  63 1023 239  63 1023       2048    5857280 82

3.1.1 硬盘总大小

255 x 63 x 30401 x 512 = 251037351936B (约为 240G , 1K = 1024B )

3.1.2 第一个分区 Start 的值 2048 怎么计算的呢?

这里的 Start 值指起始的 LBA 扇区地址。
1
2
Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 80  32  33    0 129  33  162       2048    2455552 07
(LBA值) 2048 = 255 x 63 x 0 (Cyl) +  63 x 32 (Hd) + (33 (Sec) - 1)

3.1.3 为什么后来的 Cyl 都是 1023 呢?

因为 CHS 表示中 Cylinders 用 10 bit 位, 只能表示 1024 范围内的数据。 通常情况下,BIOS 不用 CHS 寻址, 改用 LBA , 超出 CHS 表示范围如何表 示都己和 CHS 的值没有关系了。
在 CHS 表示范围内的值还将 LBA 转化为正确的 CHS 是为了兼容考虑。
其实 Disk /dev/sda: 255 heads, 63 sectors, 121601 cylinders 中的 255, 63 都是 CHS 表示中相应值能表示的最大值。

3.2 下面是一台式机上的 1T 硬盘

1
2
3
4
5
6
7
8
9
Disk /dev/sda: 255 heads, 63 sectors, 121601 cylinders

Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 00  32  33    0 254  63 1023       2048   30720000 83
 2 80 254  63 1023 254  63 1023   30722048   40960000 83
 3 00 254  63 1023 254  63 1023   71682048   40960000 83
 4 00 254  63 1023 254  63 1023  112642048 1840881664 05
 5 00 254  63 1023 254  63 1023       5732 1802235960 83
 6 00 254  63 1023 254  63 1023         63   36949437 82
255 * 63 * 121601 * 512 = 1004124635136 (约为 935G , 1K = 1024B )