MySQL: 如何使用myisam-recover-options选项?myisamrecover

适用于:

MySQL 服务器-版本4.0及以上

本文信息适用于所有平台。

 

目标

学习MySQL的myisamrecoveroptions选项并如何将它用于启动服务器时崩溃的MyISAM表的自动修复。

myisam‐recover‐options 在MySQL 5.1及更早版本中叫做mysqlrecover。

 

修复

myisam‐recover‐options选项是用于创建启动MySQL时MyISAM 的自动恢复。myisam‐recover‐options选项能使用以下值:

  • DEFAULT: 不用备份,强制,或快速检查进行恢复。
  • BACKUP: 如果数据文件在恢复时被更改,将MYD 文件的备份保存为 tbl_name‐datetime.BAK。
  • FORCE: 即使会从.MYD 文件丢失多于一行仍运行恢复。
  • QUICK: 如果没有任何delete块就不检查行。

 

myisam‐recover‐options 也允许值的组合,例如果数据文件在恢复时被更改,即使创建备份时丢失了多于一行,FORCE,BACKUP 结合恢复的使用。

 

myisam‐recover‐options的QUICK和DEFAULT值是两个最安全的选项,因为它们不删除任何数据。这也使得它们对于自动恢复是很适合的值。DEFAULT和FORCE的差异是即使FORCE不能从之前完成的语句中找到所有行,它仍被允许继续恢复。因此,建议将FORCE与BACKUP结合,使得在对MyISAM数据文件作更改之前创建一个备份。

 

所以在myisam‐recover‐options 选项使用DEFAULT 是个好方法,但如果失败的话,如果错误经常出现且可以接受潜在丢失数据的风险,建议手动修复并仅使用myisamrecover=FORCE,BACKUP。

 

你应该在执行手动修复之前创建表的备份。

 

如果你需要自动修复表而不重启MySQL ,你需要使用调度服务启 myisamchk, CHECK TABLE,且/或REPAIR TABLE 来定期检查并修复表的错误。MySQL 5.1及以上你能使用EVENTs;在MySQL

5.0及以下,你需要使用操作系统提供的scheduler。

 

如果你选择使用myisamchk,你必须确保在运行myisamchk时没有其他程序在使用表。

参见:

MyISAM Startup Options

Setting Up a MyISAM Table Maintenance Schedule

How to Repair MyISAM Tables

What is a MySQL Event and How is it Created?

 

参考

NOTE:1023216.1 How can I speed up bulk loading or repairing of MyISAM tables?

NOTE:1023264.1 What can Cause Corrupted MyISAM Tables in MySQL Server?

NOTE:1023408.1 Error: 1034 Incorrect key file for table ‘%s’; try to repair it Or ERROR 126

(HY000): Incorrect key file for table ‘%s’; try to repair it From MySQL Server

NOTE:1023752.1 Error: 1195 Table ‘%s’ is marked as crashed and last (automatic?) repair failed.

NOTE:1023780.1 Error: 1035 Old key file for table ‘%s’; repair it!

NOTE:1024132.1 What is a MySQL Event and How is it Created?

Didn’t find what you are looking for?

MySQL InnoDB表的Table is Full错误

症状

4.x, 5.0.84 及以下, 5.1.37 及以下, 带 InnoDB 插件的5.1.40及以下

使用 InnoDB 表空间且不使用 innodb_file_per_table 的所有版本

 

重现问题:

使用自动扩展 InnoDB 表空间包括使用 innodb_file_per_table 的所有版本

 

原因

4.x, 5.0.84 及以下, 5.1.37 及以下, 及带 InnoDB 插件的5.1.40 及以下

使用 fixed size InnoDB 表空间和不使用 innodb_file_per_table的所有版本

使用自动扩展InnoDB 表空间包括使用 innodb_file_per_table的所有版本

 

解决方案

Versions 4.x, 5.0.84 及以下, 5.1.37 及以下, 带 InnoDB 插件的5.1.40 及以下

使用固定大小InnoDB 表空间和不使用 innodb_file_per_table 的所有版本

使用自动扩展 InnoDB 表空间包括使用 innodb_file_per_table 的所有版本

 

 

应用于:

MySQL服务器版本4.0 及以上

本文信息适用于所有平台。

 

症状

这个错误的方式有两种可能:

4.x, 5.0.84 及以下, 5.1.37 及以下,以及带InnoDB插件的5.1.40及以下版本

当运行以下MySQL 服务器版本之一:

  • MySQL 4.0 和1的所有版本
  • 0.84 及以下
  • 不带InnoDB插件的MySQL 5.1:1.37 及以下
  • 带InnoDB插件的MySQL 5.1:1.40 及以下

 

当有多于1023个动态事务且错误信息”Table is Full”被返回到客户端。有时会发生插入错误。错误日志会包含一个更描述性的错误信息:

 

110912 14:52:14 InnoDB: Warning: cannot find a free slot for an undo log. Do you have too
InnoDB: many active transactions running concurrently?

 

所有版本 使用固定大小的 InnoDB 表空间且不使用 innodb_file_per_table

当 InnoDB 表空间设为固定大小且不使用 innodb_file_per_table 选项时,尝试将数据插入InnoDB 表时,会发生以下错误:

 

The table ‘<tablename>’ is full

 

其中<tablename> 是表名。相应的 MySQL 错误代码和SQL 状态是:

 

MySQL Error Code: 1114

SQLState: HY000

 

显示在MySQL错误日志中的错误取决于在使用的InnoDB存储引擎版本:

  • 对于带InnoDB插件的MySQL 5.1 和MySQL 5.5 及以上,错误日志包含如下错误:

 

InnoDB: Error: Data file(s) ran out of space.

Please add another data file or use ‘autoextend’ for the last data file.

110908 12:18:13 [ERROR] /usr/sbin/mysqld: The table ‘<tablename>’ is full

 

 

  • 对于MySQL/InnoDB 更早的版本(包括有InnoDB的buildin版本的MySQL 5.1 ),错误信息是:

110908 13:25:37 [ERROR] /usr/sbin/mysqld: The table ‘t1’ is full

 

即使 SHOW TABLE STATUS 或 SELECT * FROM information_schema.TABLES 显示InnoDB 表有大于0的Data_free 。

重现问题:

该问题能通过以下步骤重现:

  1. 以重新安装的MySQL启动
  2. 在首次启动MySQL之前,在你的my.cnf中有这样的设置

innodb_data_file_path = ibdata1:100M

且确保没有启动 innodb_file_per_table

  1. 启动MySQL并让InnoDB 创建数据文件
  2. 登录到MySQL并运行:

CREATE DATABASE innodbtest;

use innodbtest

CREATE TABLE t1 (id mediumint unsigned NOT NULL auto_increment PRIMARY KEY) ENGINE=InnoDB;

 

 

  1. 不断将行插入到表中,直到查询返回 The table ‘t1’ is full。
  2. 当空间即将耗尽,错误信息类似于:

 

SQLSTATE[HY000]: General error: 1114 The table ‘t1’ is full

 

 

  1. 运行SHOW TABLE STATUS:

 

mysql> SHOW TABLE STATUS LIKE 't1'\G

*************************** 1. row ***************************
Name: t1
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 3918789
Avg_row_length: 23
Data_length: 90800128
Max_data_length: 0
Index_length: 0
Data_free: 4194304
Auto_increment: 3920001
Create_time: 2011-09-08 12:14:35
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)

 

 

注意即使没有更多可用的数据,Data_free 仍是4194304 。

 

 

使用自动扩展的 InnoDB 表空间包括使用 innodb_file_per_table 的所有版本

当出现Table is full error ,在MySQL错误日志的常见症状为:

 

2014-09-15 08:33:38 7f28aeb8a700 InnoDB: Error: Write to file /mysql/data/ibdata1 failed at offset 20971520.
InnoDB: 1048576 bytes should have been written, only -1 were written.
InnoDB: Operating system error number 28.
InnoDB: Check that your OS and file system support files of this size.
InnoDB: Check also that the disk is not full or a disk quota exceeded.
InnoDB: Error number 28 means 'No space left on device'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.6/en/operating-system-error-codes.html
2014-09-15 08:33:38 7101 [ERROR] /usr/sbin/mysqld: The table 't1' is full
2014-09-15 08:33:39 7101 [ERROR] /usr/sbin/mysqld: The table 't1' is full

 

 

在Windows中,错误可能像这样:

 

 

2014-09-15 10:04:06 12AB InnoDB: Encountered a problem with file C:\ProgramData\MySQL\ibdata1
2014-09-15 10:04:06 12AB InnoDB: Disk is full. Try to clean the disk to free space.
2014-09-15 10:04:06 13D7 [ERROR] C:\Program Files\MySQL\bin\mysqld.exe: The table 't1' is full

 

 

以上是共享的表空间的错误。相似错误能在各个表空间发生。

 

原因

4.x, 5.0.84 及以下, 5.1.37 及以下, InnoDB插件的5.1.40 及以下版本

 

这是由于bug If InnoDB Runs Out of Undo Slots, It Returns Misleading ‘Table is Full’。在MySQL 5.1 及以下 InnoDB 支持最多1023个动态事务。要启动更多将会导致错误或在受该bug影响的版本中可能产生声明assertion。

 

使用固定大小的InnoDB 表空间和不使用 innodb_file_per_table 的所有版本

 

该问题是由于InnoDB 耗尽了在共享表空间中的可用空间。在每个参考手册中,Table is full 错误表示磁盘用尽或表达到最大。对于InnoDB,当InnoDB被设为有共享的表空间,InnoDB 表空间的大小 (数据文件) 决定了表的最大空间。

 

InnoDB 表空间包含默认大小为16KB的数据页。有可能一些页没有被完全使用,但是实际上不太可能对新的数据进行提示。因此,SHOW TABLE STATUS报告仍有空间而实际上无法再插入任何数据是有可能的。

 

参见MySQL参考手册中以下页:

  • The table is full
  • Limits on Table Size
  • Configuring InnoDB
  • InnoDB File Space Management

 

使用自动扩展的InnoDB 表空间包括使用 innodb_file_per_table 的所有版本

在这个情况下,起因可能是:

储存表空间的磁盘已满。

已达到设置的磁盘配额。

表空间文件达到文件系统支持的最大尺寸。

 

解决方案

4.x, 5.0.84 及以下, 5.1.37 及以下,和带InnoDB插件的5.1.40及以下版本

解决方案是升级到MySQL的补丁版本。以下版本被打过补丁:

  • MySQL 5.0: 5.0.85及以上
  • 不带InnoDB插件的MySQL 5.1:1.38及以上
  • 带InnoDB插件的MySQL 5.1:1.41及以上
  • MySQL 5.5 及以上:所有版本

 

建议升级到可用的最新GA版本。

 

在升级之前总是创建数据库部分!这包括schema,数据和数据库需要执行的程序(函数,触发器等)。安全总是最好的策略,所以如果在升级过程中有一些问题,很容易恢复到之前的版本。

 

升级教程参见:

  • Downloading MySQL Server
  • 升级或下载MySQL。检查表或索引是否必须重建的部分尤其重要。对下载的版本使用页: 5, 5.1, 5.0。参见 How to Upgrade your Existing MySQL Server to MySQL 5.6 Version 获得更多升级MySQL的帮助。

 

总是在对生产服务器执行升级之前开发或阶段系统中进行测试。

 

使用固定大小的InnoDB表空间和不使用 innodb_file_per_table的所有版本

解决方案使让InnoDB表空间增长,通过执行以下步骤完成:

 

总是在更改应用于生产之前,在开发或阶段系统中尝试步骤。

 

  1. 停止MySQL
  2. 在你喜欢的编辑器中打开MySQL配置文件。
  3. 找到配置innodb_data_file_path 选项的行
  4. 添加一个新表空间或让最近的表空间自动扩展:
  5. 将 innodb_data_file_path 设为

innodb_data_file_path = ibdata1:100M;ibdata2:100M

或类似的

  1. 将 innodb_data_file_path 设为

innodb_data_file_path = ibdata1:100M:autoextend

  1. 保存MySQL配置文件
  2. 再次启动MySQL
  3. 确认现在能够再次将数据插入InnoDB表
  4. 将解决方法迁移到合适的其他环境。

 

参见MySQL参考手册中以下页:

Configuring InnoDB

Adding, Removing, or Resizing InnoDB Data and Log Files

 

使用自动扩展的InnoDB 表空间包括使用 innodb_file_per_table 的所有版本

由于原因是无法进一步增加表空间文件的大小,解决方法包括:

  • 确保表空间文件储存的路径有多余的磁盘空间(参见以下建议,如何释放磁盘空间)。

不要为了释放空间而删除任何InnoDB文件,包括共享的表空间。没有它的这些文件,InnoDB将无法启动。

如何取回空间的教程,参见以下。

  • 确保没有预设的定量会阻止表空间文件的增长。
  • 确保文件系统支持的最大文件尺寸还未达到。如果这是Table is full错误的原因,一些解决方案如下:
    1. 通过你将所有表储存在共享的表空间 (innodb_file_per_table = 0):
      1. 另外创建一个共享的表空间文件。
      2. 或者,你能另外创建一个额外共享的表空间文件启用 innodb_file_per_table ,从而能将表移出共享的表空间。注意到这不会降低共享的表空间大小。参见MySQL Server Variable: innodb_file_per_table获得关于innodb_file_per_table的更多信息。
    2. 对于每个表的表空间的文件,对表进行分区。对已分区的表,每个分区在 自己的表空间中且innodb_file_per_table = 1,所以这是你能将总大小分割到多个文件。

 

释放磁盘空间的可能操作有:

 

  • 使用OPTIMIZE TABLE <table_name>取回每个表空间的空闲空间

这需要重建在表空间文件位置的表。所以只有当你已经释放了空间或将表迁移到另外的位置才有作用。(参见以下)

  • 要取回在共享表空间文件中的文件,参见:How to Reclaim Unused Space and Decrease InnoDB ibdata1 Data File Size.
  • 如果错误日志,慢查询日志,一般查询日志,审计日志等储存在与表空间相同的磁盘。考虑重定向停止并压缩旧日志或将旧日志移动到其他磁盘。参见:
    1. 服务器日志维护
    2. audit_log_rotate_on_size
  • 如果二进制日志位于与数据相同的磁盘上,考虑清楚旧的二进制日志。

确保被清楚二进制日志是不再需要的,例,用于复制或时间点恢复。如果二进制不再需要用于复制但仍要用于恢复,你能在清楚日志之前创建备份。

确保你使用PURGE BINARY LOGS 命令来删除旧的二进制日志。

  • 在MySQL 5.6 中,你能使用 InnoDB native links将在自己tablespace的表空间移到另一个磁盘。
  • 将日志移到另一个磁盘。参见:
    1. What is the General Query Log and How to Control Where the Log is Stored?
    2. What is the Slow Query Log and How to Control Where the Log is Stored and What is Logged?
    3. –log_ error
    4. –audit_ log_file

 

什么导致了MySQL服务器中的MyISAM 表损坏?

 

应用于:

MySQL 服务器-版本:4.0 到 5.5 –发行版:到5.5

MySQL 服务器-版本:4.0 以上–发行版:4.0 以上

MySQL 服务器-版本:4.0 到 5.5 –发行版:4.0 到 5.5

 

所有平台

 

目标

说明MyISAM 表损坏的具体原因

 

解决方案

 

MyISAM 存储引擎非常可靠。但如果时常遇到MyISAM 表损坏,你最好思考导致这个问题的原因。在查询数据时,以下错误信息通常意味着表损坏:

 

Error 1034 Incorrect key file for table: ‘…’. Try to repair it

 

或包含以下错误号码之一的信息:

 

Error 126 = Index file is crashed

Error 127 = Record-file is crashed

Error 134 = Record was already deleted (or record file crashed)

Error 144 / Error 1195 = Table is crashed and last repair failed

Error 145 / Error 1194 = Table was marked as crashed and should be repaired

 

当查询本该查找到在表中的行但没有找到,或当一个查询返回不完整的数据,也可以假定发生了损坏。你可以使用CHECK TABLE 语句来验证MyISAM 表是否损坏。

 

MyISAM的损坏可能由多种因素导致。以可能性从大到小排序,它们依次为:

  1. 由于服务器崩溃,意外关闭,或硬件错误引起的损坏
  • 如果在写的过程中,mysqld进程被杀掉或崩溃可能会导致损坏。
  • 由于电源故障导致运行MySQL的服务器关闭可能会导致损坏。
  • 还可能由于硬件错误导致,如服务器的硬盘问题,这比之前的问题引起损坏的可能性低。
  • RAM中的损坏;重启硬件可能解决这个罕见的问题;如果在操作系统缓存中有损坏的数据,有时只需重启,不需要通断电就能解决这个问题。这个情况比较罕见,但如果你的硬件故障,发生频率就会很高。

服务器重启时的自动修复通常会解决这个问题,但有时需要使用REPAIR TABLE SQL 语句以及更深入的检查选项。当你的表很大,而服务器离线并有强制更快修复的选项时,可以使用myisamchk 。如果你有许多CPU 内核且表中有许多索引,你应该尝试myisamchk 选项先来使用多个线程,因为这通常会更快;这个选项失败时而会有报告,所以不太可能尝试后发现只需要单个线程。

 

  1. 由于其他程序导致的损坏
  • 如果你在使用外部程序,如myisamchk,这会在服务器运行时对表进行更改,你就很可能遇到损坏。
  • 部分或反病毒软件也经常导致损坏,有时由于恢复表的旧版,或由于检验需要的文件。

这些情况的第一步是找出是什么更改了文件。修复表只是暂时的方法。

  1. 由于bug导致的损坏
  • 使用在2007年夏季之前版本的服务器建设。从2006年开始到2007年,MySQL执行了系统的测试来找出罕见且难以复制的MyISAM损坏bug。大约在2007年夏季,我们看到几乎所有bug相关的损坏问题来自旧版本,有广泛修复的较新版本很少受到影响。你能通过将版本升级到接近于2007夏季的版本,最好是最接近的,来消除遇到损坏的可能性,越接近的版本越好。
  • 如果bug仍导致损坏,你应该首先查看最近引入的服务器功能和情况,其中并发级别很高的区域是最可能有问题的。现今,新的损坏bug通常涉及具体客户的语句结合和高并发性,或新功能和高并发性。

你能查找在错误认知中最近重启的mysqld 来验证表是否由于服务器崩溃而损坏。如果没有错误信息表明问题是由于服务器故障,且损坏看上去发生在正常操作期间,这可能是bug。因此,你应该尝试创建一个可复制的测试以反映出问题并通过在My Oracle Support中开启一个Support Request 来报告问题。

再说一次,你能用REPAIR TABLE SQL 语句来修改损坏的MyISAM表。此外,当 mysqld不在运行时,你能用myisamchk 命令来检查或修复表。

 

 

GoldenGate OGG 1403错误解决方法

1. 错误描述

WARNING OGG-01154 Oracle GoldenGate Delivery for Oracle, repyxb.prm: SQL error 1403 mapping SGPM.P_SMS_SEND to SGPM.P_SMS_SEND.

WARNING OGG-01003 Oracle GoldenGate Delivery for Oracle, repyxb.prm:  Repositioning to rba 2509817 in seqno 1.

ERROR OGG-01296 Oracle GoldenGate Delivery for Oracle, repyxb.prm:  Error mapping from SGPM.P_SMS_SEND to SGPM.P_SMS_SEND.

ERROR OGG-01668 Oracle GoldenGate Delivery for Oracle, repyxb.prm:  PROCESS ABENDING.

2. 错误原因和分析

SQL ERROR 1403属数据错误,指记录无法投递到目标数据库,需通过查看错误信息及discarded文件,到两端库寻找相应记录,并结合logdump工具分析队列中的实际数据,分析出现该错误的原因,进而解决该问题。

造成该错误的可能原因:

  • 两端表结构不一致
  • 附加日志错误
  • 初始化方法错误导致不一致
  • 目标端级联删除、trigger没有被禁止
  • 该表存在不写日志的DML操作

3. 处理方法

3.1 两端表结构不一致

重新初始化该表,初始化方法见《国家电网公司网省数据级容灾GoldenGate运维方案》。

3.2 附加日志错误

在源端确认该表附加日志是否为enable状态,执行命令:

GGSCI>INFO TRANDATA schema.table_name

如果不是,重新添加附加日志,执行命令

GGSCI>ADD TRANDATA schema.table_name

加完附加日志后需要重新对该表执行初始化,具体方法请参照运维方案。

3.3 初始化方法错误导致数据不一致

GG在执行删改操作时,由于初始化方法错误造成的数据不一致,使得GG删除的记录不存在,或修改的数据前影像不一致。此时,可通过logdump观察具体错误,如果记录条数不多,则可手动修复该错误。如果记录数非常多,则需对该表进行重新初始化或在replicat进程中添加handlecollisions参数(加handlecollisions参数的前提为该replicat进程复制的表均有主键或唯一约束)。

3.4 目标端级联删除、trigger没有被禁止

删除目标端trigger及主外键约束即可。

禁止trigger:

禁止主外键约束:

3.5 该表存在不写日志的DML操作

当表处于logging状态且使用了以下数据装载模式+nologging时DML将不会被写入数据库日志,OGG无法捕获到:

❍ /*+ APPEND */ hint

❍ /*+ BUFFER */ hint

❍ /*+ PARALLEL */ hint

❍ SQLLDR with DIRECT=TRUE

请首先检查表是否处于logging mode,然后从应用方面检查是否存在这些限制。如果有需要调整表为logging模式,对表执行重新初始化,具体方法请参照运维方案。

3.6 定时任务

观察数据库是否存在定时任务自动修改数据。

同样,对于操作系统级也进行检查,是否有脚本自动修改数据库中数据。

如有以上现象,请禁止这些任务,对已经受影响的表执行初始化。

3.8 数据初始化带来的不一致

如果数据初始化时候没有使用SCN号做恢复和启动OGG进程,则可能会丢失部分数据,在日后的运行过程中报告1403错误。

3.9 人为修改OGG进程检查点带来的数据不一致

如果使用了alter extract/replicat等操作修改过OGG的检查点,则可能会出现丢失数据或者部分时段数据重复现象,造成运行期间报告1403错误。

3.10 人为修改目标端数据

人为失误修改目标数据也会造成两端数据不一致。

深入了解Oracle ASM(二):ASM File number 1 文件目录

ASM file number 1 – the File Directory

 

ASM文件目录File Directory针对本Disk Group中的每一个文件包含一条记录。该记录指向该文件的前60个数据盘区extents,必要时还包括间接盘区indirect extents。该文件目录在必要容纳更多文件数目时会自动增长。每一个文件目录记录保持更新以下文件信息:

 

  • 文件大小
  • 该文件的块大小
  • 文件种类,例如:数据文件,ASM元数据文件,在线日志,归档日志,控制文件等等
  • 文件冗余度:外部、2路或者3路镜像
  • 条带化配置,coarse or fine
  • 到前60个extent的直接盘区指针(direct extent pointer)
  • 300个间接盘区指针(indirect extent pointers)
  • 创建时间戳
  • 最后修改或更新时间戳
  • 指向别名目录中的用户别名和文件名

ASM 1号文件 file number 1

文件号file number是文件目录中找到对应文件记录的重要索引键。 其中第一条记录是该文件目录自身。为了找出过期的文件号,所以在每个文件创建时都生成了一个唯一的32 bit的识别号incarnation number。由此,disk group的ID+ file number + 该incarnation number 可以做到唯一识别某个指定文件。

 

请注意,约定俗成地将ASM文件的第一个block称为0号块–block zero。 0号块通常包含十分重要的接口信息。

 

文件目录file directory 的位置 

 

为了找出file directory所在AU的位置,我们需要使用kfed工具浏览ASM disk header磁盘头部0号AU中的kfdhdb.f1b1locn信息,例如我们使用kfed查看asm disk /dev/asm-diski上的信息:

 

 

[grid@localhost ~]$ kfed read /dev/asm-diski  aun=0 |less

kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                            1 ; 0x002: KFBTYP_DISKHEAD
kfbh.datfmt:                          1 ; 0x003: 0x01
kfbh.block.blk:                       0 ; 0x004: blk=0
kfbh.block.obj:              2147483650 ; 0x008: disk=2
kfbh.check:                  2593903300 ; 0x00c: 0x9a9bd2c4
kfbh.fcn.base:                      217 ; 0x010: 0x000000d9
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kfdhdb.driver.provstr:         ORCLDISK ; 0x000: length=8
kfdhdb.driver.reserved[0]:            0 ; 0x008: 0x00000000
kfdhdb.driver.reserved[1]:            0 ; 0x00c: 0x00000000
kfdhdb.driver.reserved[2]:            0 ; 0x010: 0x00000000
kfdhdb.driver.reserved[3]:            0 ; 0x014: 0x00000000
kfdhdb.driver.reserved[4]:            0 ; 0x018: 0x00000000
kfdhdb.driver.reserved[5]:            0 ; 0x01c: 0x00000000
kfdhdb.compat:                186646528 ; 0x020: 0x0b200000
kfdhdb.dsknum:                        2 ; 0x024: 0x0002
kfdhdb.grptyp:                        3 ; 0x026: KFDGTP_HIGH
kfdhdb.hdrsts:                        3 ; 0x027: KFDHDR_MEMBER
kfdhdb.dskname:           SYSTEMDG_0002 ; 0x028: length=13
kfdhdb.grpname:                SYSTEMDG ; 0x048: length=8
kfdhdb.fgname:            SYSTEMDG_0002 ; 0x068: length=13
kfdhdb.capname:                         ; 0x088: length=0
kfdhdb.crestmp.hi:             32982958 ; 0x0a8: HOUR=0xe DAYS=0x1d MNTH=0x1 YEAR=0x7dd
kfdhdb.crestmp.lo:           3878604800 ; 0x0ac: USEC=0x0 MSEC=0x3b4 SECS=0x32 MINS=0x39
kfdhdb.mntstmp.hi:             32983461 ; 0x0b0: HOUR=0x5 DAYS=0xd MNTH=0x2 YEAR=0x7dd
kfdhdb.mntstmp.lo:            474934272 ; 0x0b4: USEC=0x0 MSEC=0x3bb SECS=0x4 MINS=0x7
kfdhdb.secsize:                     512 ; 0x0b8: 0x0200
kfdhdb.blksize:                    4096 ; 0x0ba: 0x1000
kfdhdb.ausize:                  1048576 ; 0x0bc: 0x00100000
kfdhdb.mfact:                    113792 ; 0x0c0: 0x0001bc80
kfdhdb.dsksize:                    3072 ; 0x0c4: 0x00000c00
kfdhdb.pmcnt:                         2 ; 0x0c8: 0x00000002
kfdhdb.fstlocn:                       1 ; 0x0cc: 0x00000001
kfdhdb.altlocn:                       2 ; 0x0d0: 0x00000002
kfdhdb.f1b1locn:                      2 ; 0x0d4: 0x00000002
kfdhdb.redomirrors[0]:                0 ; 0x0d8: 0x0000
kfdhdb.redomirrors[1]:                0 ; 0x0da: 0x0000
kfdhdb.redomirrors[2]:                0 ; 0x0dc: 0x0000
kfdhdb.redomirrors[3]:                0 ; 0x0de: 0x0000
kfdhdb.dbcompat:              168820736 ; 0x0e0: 0x0a100000
kfdhdb.grpstmp.hi:             32982958 ; 0x0e4: HOUR=0xe DAYS=0x1d MNTH=0x1 YEAR=0x7dd
kfdhdb.grpstmp.lo:           3878197248 ; 0x0e8: USEC=0x0 MSEC=0x226 SECS=0x32 MINS=0x39
kfdhdb.vfstart:                       0 ; 0x0ec: 0x00000000
kfdhdb.vfend:                         0 ; 0x0f0: 0x00000000
kfdhdb.spfile:                       38 ; 0x0f4: 0x00000026
kfdhdb.spfflg:                        1 ; 0x0f8: 0x00000001

//也可以通过查询X$KFFXP视图找出该FILE NUMBER=1的文件的Allocation Units

select disk_kffxp, AU_kffxp, xnum_kffxp
  from x$kffxp
 where group_kffxp = 3 -- Diskgroup 3 (GROUPB)
   and number_kffxp = 1 -- File 1 (file directory)
   /

DISK_KFFXP   AU_KFFXP XNUM_KFFXP
---------- ---------- ----------
         0          2          0
         1          2          0
         2          2          0
         2         46          1
         3         44          1
         0         46          1

 

 

 

上面显示的结果显示 在disk number =0 的ASM Disk 上的allocation units 2属于file number=1的file directory, 同理 在disk number =0 的ASM Disk 上的allocation units 46也属于file number=1的file directory。

在1MB allocation units大小,4k ASM block大小的前提下,第一个allocation unit可以存放255个目录记录(256*4k=1MB)。 由于前255个文件是为ASM元数据保留的,所以第一个allocation unit仅记录ASM元数据文件第一到第六个。剩下的allocation unit(46)则存放接下来的255个ASM文件。

 

文件目录结构

 

Allocation unit=2 的block 1描述了该ASM 1号文件file directory自身。该块的前部分包含了标准的头部信息,并显示该块的类型为KFBTYP_FILEDIR。 在该kfffdb结构之后,该file directory的每一个block包含描述文件物理属性和盘区指针的信息, 以及指向所有间接盘区的指针。

以下是aun=2 block=1的file directory信息:

 

 

 

 

[grid@localhost ~]$ kfed read /dev/asm-diski aun=2 blkn=1  > block.log
[grid@localhost ~]$ vi block.log 

kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                            4 ; 0x002: KFBTYP_FILEDIR
kfbh.datfmt:                          1 ; 0x003: 0x01
kfbh.block.blk:                       1 ; 0x004: blk=1
kfbh.block.obj:                       1 ; 0x008: file=1
kfbh.check:                  3254018873 ; 0x00c: 0xc1f46339
kfbh.fcn.base:                      493 ; 0x010: 0x000001ed
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kfffdb.node.incarn:                   1 ; 0x000: A=1 NUMM=0x0
kfffdb.node.frlist.number:   4294967295 ; 0x004: 0xffffffff
kfffdb.node.frlist.incarn:            0 ; 0x008: A=0 NUMM=0x0
kfffdb.hibytes:                       0 ; 0x00c: 0x00000000
kfffdb.lobytes:                 2097152 ; 0x010: 0x00200000
kfffdb.xtntcnt:                       6 ; 0x014: 0x00000006
kfffdb.xtnteof:                       6 ; 0x018: 0x00000006
kfffdb.blkSize:                    4096 ; 0x01c: 0x00001000
kfffdb.flags:                         1 ; 0x020: O=1 S=0 S=0 D=0 C=0 I=0 R=0 A=0
kfffdb.fileType:                     15 ; 0x021: 0x0f
kfffdb.dXrs:                         19 ; 0x022: SCHE=0x1 NUMB=0x3
kfffdb.iXrs:                         19 ; 0x023: SCHE=0x1 NUMB=0x3
kfffdb.dXsiz[0]:             4294967295 ; 0x024: 0xffffffff
kfffdb.dXsiz[1]:                      0 ; 0x028: 0x00000000
kfffdb.dXsiz[2]:                      0 ; 0x02c: 0x00000000
kfffdb.iXsiz[0]:             4294967295 ; 0x030: 0xffffffff
kfffdb.iXsiz[1]:                      0 ; 0x034: 0x00000000
kfffdb.iXsiz[2]:                      0 ; 0x038: 0x00000000
kfffdb.xtntblk:                       6 ; 0x03c: 0x0006
kfffdb.break:                        60 ; 0x03e: 0x003c
kfffdb.priZn:                         0 ; 0x040: KFDZN_COLD
kfffdb.secZn:                         0 ; 0x041: KFDZN_COLD
kfffdb.ub2spare:                      0 ; 0x042: 0x0000

 

 

其中字段的含义:

 

 

KFBTYP_FILEDIR // block type = file directory block
kfffdb.node.incarn: File incarnation information
kfffdb.hibytes File size (high bytes)
kfffdb.lobyte 2097152 ; 0x010: 0x00200000 File size (low bytes) 2097152 ==》2MB大小
kfffdb.xtntcnt: 6 ; 0x014: 0x00000006 // 6 extents for this file
kfffdb.xtnteof: 6 ; 0x018: 0x00000006 // 6 extents before eof
kfffdb.blkSize: 4096 ; 0x01c: 0x00001000 // 标准ASM block大小
kfffdb.flags: 1 ; 0x020: O=1 S=0 S=0 D=0 C=0 I=0 R=0 A=0
// Flag definitions
O – File is original, not snapshot
S – File is striped
S – Strict allocation policy
D – File is damaged
C – File creation is committed
I – File has empty indirect block
R – File has known at-risk value
A – The at-risk value itsefl

 

接下来看一个ASM metadata 文件的实际目录记录,我们就查看aun=2的 blkn=4

 

 

[grid@localhost ~]$ kfed read /dev/asm-diski aun=2 blkn=4|less

kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                            4 ; 0x002: KFBTYP_FILEDIR
kfbh.datfmt:                          1 ; 0x003: 0x01
kfbh.block.blk:                       4 ; 0x004: blk=4
kfbh.block.obj:                       1 ; 0x008: file=1
kfbh.check:                  3786097185 ; 0x00c: 0xe1ab4221
kfbh.fcn.base:                      206 ; 0x010: 0x000000ce
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kfffdb.node.incarn:                   1 ; 0x000: A=1 NUMM=0x0
kfffdb.node.frlist.number:   4294967295 ; 0x004: 0xffffffff
kfffdb.node.frlist.incarn:            0 ; 0x008: A=0 NUMM=0x0
kfffdb.hibytes:                       0 ; 0x00c: 0x00000000
kfffdb.lobytes:                 8331264 ; 0x010: 0x007f2000
kfffdb.xtntcnt:                      24 ; 0x014: 0x00000018
kfffdb.xtnteof:                      24 ; 0x018: 0x00000018
kfffdb.blkSize:                    4096 ; 0x01c: 0x00001000
kfffdb.flags:                         1 ; 0x020: O=1 S=0 S=0 D=0 C=0 I=0 R=0 A=0
kfffdb.fileType:                     15 ; 0x021: 0x0f
kfffdb.dXrs:                         19 ; 0x022: SCHE=0x1 NUMB=0x3
kfffdb.iXrs:                         19 ; 0x023: SCHE=0x1 NUMB=0x3
kfffdb.dXsiz[0]:             4294967295 ; 0x024: 0xffffffff
kfffdb.dXsiz[1]:                      0 ; 0x028: 0x00000000
kfffdb.dXsiz[2]:                      0 ; 0x02c: 0x00000000
kfffdb.iXsiz[0]:             4294967295 ; 0x030: 0xffffffff
kfffdb.iXsiz[1]:                      0 ; 0x034: 0x00000000
kfffdb.iXsiz[2]:                      0 ; 0x038: 0x00000000
kfffdb.xtntblk:                      24 ; 0x03c: 0x0018
kfffdb.break:                        60 ; 0x03e: 0x003c
kfffdb.priZn:                         0 ; 0x040: KFDZN_COLD
kfffdb.secZn:                         0 ; 0x041: KFDZN_COLD
kfffdb.ub2spare:                      0 ; 0x042: 0x0000
kfffdb.alias[0]:             4294967295 ; 0x044: 0xffffffff
kfffdb.alias[1]:             4294967295 ; 0x048: 0xffffffff
kfffdb.strpwdth:                      0 ; 0x04c: 0x00
kfffdb.strpsz:                        0 ; 0x04d: 0x00
kfffdb.usmsz:                         0 ; 0x04e: 0x0000
kfffdb.crets.hi:               32982958 ; 0x050: HOUR=0xe DAYS=0x1d MNTH=0x1 YEAR=0x7dd
kfffdb.crets.lo:             3878730752 ; 0x054: USEC=0x0 MSEC=0x2f SECS=0x33 MINS=0x39
kfffdb.modts.hi:               32982958 ; 0x058: HOUR=0xe DAYS=0x1d MNTH=0x1 YEAR=0x7dd
kfffdb.modts.lo:             3878730752 ; 0x05c: USEC=0x0 MSEC=0x2f SECS=0x33 MINS=0x39
kfffdb.dasz[0]:                       0 ; 0x060: 0x00
kfffdb.dasz[1]:                       0 ; 0x061: 0x00
kfffdb.dasz[2]:                       0 ; 0x062: 0x00
kfffdb.dasz[3]:                       0 ; 0x063: 0x00
kfffdb.permissn:                      0 ; 0x064: 0x00
kfffdb.ub1spar1:                      0 ; 0x065: 0x00
kfffdb.ub2spar2:                      0 ; 0x066: 0x0000
kfffdb.user.entnum:                   0 ; 0x068: 0x0000
kfffdb.user.entinc:                   0 ; 0x06a: 0x0000
kfffdb.group.entnum:                  0 ; 0x06c: 0x0000
kfffdb.group.entinc:                  0 ; 0x06e: 0x0000
kfffdb.spare[0]:                      0 ; 0x070: 0x00000000
kfffdb.spare[1]:                      0 ; 0x074: 0x00000000
kfffdb.spare[2]:                      0 ; 0x078: 0x00000000
kfffdb.spare[3]:                      0 ; 0x07c: 0x00000000
kfffdb.spare[4]:                      0 ; 0x080: 0x00000000
kfffdb.spare[5]:                      0 ; 0x084: 0x00000000
kfffdb.spare[6]:                      0 ; 0x088: 0x00000000
kfffdb.spare[7]:                      0 ; 0x08c: 0x00000000
kfffdb.spare[8]:                      0 ; 0x090: 0x00000000
kfffdb.spare[9]:                      0 ; 0x094: 0x00000000
kfffdb.spare[10]:                     0 ; 0x098: 0x00000000
kfffdb.spare[11]:                     0 ; 0x09c: 0x00000000
kfffdb.usm:                             ; 0x0a0: length=0
kfffde[0].xptr.au:                   36 ; 0x4a0: 0x00000024
kfffde[0].xptr.disk:                  1 ; 0x4a4: 0x0001
kfffde[0].xptr.flags:                 0 ; 0x4a6: L=0 E=0 D=0 S=0
kfffde[0].xptr.chk:                  15 ; 0x4a7: 0x0f
kfffde[1].xptr.au:                   45 ; 0x4a8: 0x0000002d
kfffde[1].xptr.disk:                  0 ; 0x4ac: 0x0000
kfffde[1].xptr.flags:                 0 ; 0x4ae: L=0 E=0 D=0 S=0
kfffde[1].xptr.chk:                   7 ; 0x4af: 0x07
kfffde[2].xptr.au:                   34 ; 0x4b0: 0x00000022
kfffde[2].xptr.disk:                  3 ; 0x4b4: 0x0003
kfffde[2].xptr.flags:                 0 ; 0x4b6: L=0 E=0 D=0 S=0
kfffde[2].xptr.chk:                  11 ; 0x4b7: 0x0b
kfffde[3].xptr.au:                   36 ; 0x4b8: 0x00000024
kfffde[3].xptr.disk:                  0 ; 0x4bc: 0x0000
kfffde[3].xptr.flags:                 0 ; 0x4be: L=0 E=0 D=0 S=0
kfffde[3].xptr.chk:                  14 ; 0x4bf: 0x0e
kfffde[4].xptr.au:                   43 ; 0x4c0: 0x0000002b
kfffde[4].xptr.disk:                  3 ; 0x4c4: 0x0003
kfffde[4].xptr.flags:                 0 ; 0x4c6: L=0 E=0 D=0 S=0
kfffde[4].xptr.chk:                   2 ; 0x4c7: 0x02
kfffde[5].xptr.au:                   37 ; 0x4c8: 0x00000025
kfffde[5].xptr.disk:                  1 ; 0x4cc: 0x0001
kfffde[5].xptr.flags:                 0 ; 0x4ce: L=0 E=0 D=0 S=0
kfffde[5].xptr.chk:                  14 ; 0x4cf: 0x0e
kfffde[6].xptr.au:                   42 ; 0x4d0: 0x0000002a
kfffde[6].xptr.disk:                  2 ; 0x4d4: 0x0002
kfffde[6].xptr.flags:                 0 ; 0x4d6: L=0 E=0 D=0 S=0
kfffde[6].xptr.chk:                   2 ; 0x4d7: 0x02
kfffde[7].xptr.au:                   40 ; 0x4d8: 0x00000028
kfffde[7].xptr.disk:                  1 ; 0x4dc: 0x0001
kfffde[7].xptr.flags:                 0 ; 0x4de: L=0 E=0 D=0 S=0
kfffde[7].xptr.chk:                   3 ; 0x4df: 0x03
kfffde[8].xptr.au:                   39 ; 0x4e0: 0x00000027
kfffde[8].xptr.disk:                  3 ; 0x4e4: 0x0003
kfffde[8].xptr.flags:                 0 ; 0x4e6: L=0 E=0 D=0 S=0

 

 

其中字段的含义:

kfffdb.lobytes: 8331264 ; 0x010: 0x007f2000 ==>说明文件大小为8331264bytes
kfffdb.xtntcnt: 24 ; 0x014: 0x00000018
kfffdb.xtnteof: 24 ; 0x018: 0x00000018 ==> 说明该文件目前共24个extents
kfffdb.blkSize: 4096 ; 0x01c: 0x00001000 ==> 4k的ASM Block size
kfffdb.fileType: 15 ; 0x021: 0x0f filetype=15 说明是ASM Metadata File
kfffde[0].xptr.au: 36 ; 0x4a0: 0x00000024 file number=4 的第一extent指向36号 AU
kfffde[0].xptr.disk: 1 ; 0x4a4: 0x0001 Disk number 1
kfffde[1].xptr.au: 45 ; 0x4a8: 0x0000002d file number=4 的第二extent指向45号AU
kfffde[2].xptr.au: 4294967295 ; 0x4b0: 0xfffffff 若 kfffde[N].xptr.au=4294967295 说明该FILE没有更多extent了

 

AU的指针情况, 可以这样查看:

 

 

[grid@localhost ~]$ kfed read /dev/asm-diski aun=2 blkn=4| egrep "xptr.au|xptr.disk"|less

kfffde[0].xptr.au:                   36 ; 0x4a0: 0x00000024
kfffde[0].xptr.disk:                  1 ; 0x4a4: 0x0001
kfffde[1].xptr.au:                   45 ; 0x4a8: 0x0000002d
kfffde[1].xptr.disk:                  0 ; 0x4ac: 0x0000
kfffde[2].xptr.au:                   34 ; 0x4b0: 0x00000022
kfffde[2].xptr.disk:                  3 ; 0x4b4: 0x0003
kfffde[3].xptr.au:                   36 ; 0x4b8: 0x00000024
kfffde[3].xptr.disk:                  0 ; 0x4bc: 0x0000
kfffde[4].xptr.au:                   43 ; 0x4c0: 0x0000002b
kfffde[4].xptr.disk:                  3 ; 0x4c4: 0x0003
kfffde[5].xptr.au:                   37 ; 0x4c8: 0x00000025
kfffde[5].xptr.disk:                  1 ; 0x4cc: 0x0001
kfffde[6].xptr.au:                   42 ; 0x4d0: 0x0000002a
kfffde[6].xptr.disk:                  2 ; 0x4d4: 0x0002
kfffde[7].xptr.au:                   40 ; 0x4d8: 0x00000028
kfffde[7].xptr.disk:                  1 ; 0x4dc: 0x0001
kfffde[8].xptr.au:                   39 ; 0x4e0: 0x00000027
kfffde[8].xptr.disk:                  3 ; 0x4e4: 0x0003
kfffde[9].xptr.au:                   40 ; 0x4e8: 0x00000028
kfffde[9].xptr.disk:                  3 ; 0x4ec: 0x0003
kfffde[10].xptr.au:                  41 ; 0x4f0: 0x00000029
kfffde[10].xptr.disk:                 1 ; 0x4f4: 0x0001
kfffde[11].xptr.au:                  40 ; 0x4f8: 0x00000028
kfffde[11].xptr.disk:                 0 ; 0x4fc: 0x0000
kfffde[12].xptr.au:                  42 ; 0x500: 0x0000002a
kfffde[12].xptr.disk:                 1 ; 0x504: 0x0001
kfffde[13].xptr.au:                  41 ; 0x508: 0x00000029
kfffde[13].xptr.disk:                 0 ; 0x50c: 0x0000
kfffde[14].xptr.au:                  43 ; 0x510: 0x0000002b
kfffde[14].xptr.disk:                 2 ; 0x514: 0x0002
kfffde[15].xptr.au:                  42 ; 0x518: 0x0000002a
kfffde[15].xptr.disk:                 0 ; 0x51c: 0x0000
kfffde[16].xptr.au:                  41 ; 0x520: 0x00000029
kfffde[16].xptr.disk:                 3 ; 0x524: 0x0003
kfffde[17].xptr.au:                  43 ; 0x528: 0x0000002b
kfffde[17].xptr.disk:                 1 ; 0x52c: 0x0001
kfffde[18].xptr.au:                  44 ; 0x530: 0x0000002c
kfffde[18].xptr.disk:                 2 ; 0x534: 0x0002
kfffde[19].xptr.au:                  43 ; 0x538: 0x0000002b
kfffde[19].xptr.disk:                 0 ; 0x53c: 0x0000
kfffde[20].xptr.au:                  44 ; 0x540: 0x0000002c
kfffde[20].xptr.disk:                 1 ; 0x544: 0x0001
kfffde[20].xptr.disk:                 1 ; 0x544: 0x0001
kfffde[21].xptr.au:                  42 ; 0x548: 0x0000002a
kfffde[21].xptr.disk:                 3 ; 0x54c: 0x0003
kfffde[22].xptr.au:                  45 ; 0x550: 0x0000002d
kfffde[22].xptr.disk:                 2 ; 0x554: 0x0002
kfffde[23].xptr.au:                  45 ; 0x558: 0x0000002d
kfffde[23].xptr.disk:                 1 ; 0x55c: 0x0001
kfffde[24].xptr.au:          4294967295 ; 0x560: 0xffffffff
kfffde[24].xptr.disk:             65535 ; 0x564: 0xffff
kfffde[25].xptr.au:          4294967295 ; 0x568: 0xffffffff
kfffde[25].xptr.disk:             65535 ; 0x56c: 0xffff
kfffde[26].xptr.au:          4294967295 ; 0x570: 0xffffffff
kfffde[26].xptr.disk:             65535 ; 0x574: 0xffff
kfffde[27].xptr.au:          4294967295 ; 0x578: 0xffffffff

可以这样验证一下

select disk_kffxp, AU_kffxp, xnum_kffxp
from x$kffxp
where group_kffxp = 3 -- Diskgroup 3 (GROUPB)
and number_kffxp =4
/

DISK_KFFXP   AU_KFFXP XNUM_KFFXP
---------- ---------- ----------
         1         36          0
         0         45          0
         3         34          0
         0         36          1
         3         43          1
         1         37          1
         2         42          2
         1         40          2
         3         39          2
         3         40          3
         1         41          3
         0         40          3
         1         42          4
         0         41          4
         2         43          4
         0         42          5
         3         41          5
         1         43          5
         2         44          6
         0         43          6
         1         44          6
         3         42          7
         2         45          7
         1         45          7

 

 

找出数据文件对应的目录记录directory entry:

SQL> select GROUP_NUMBER, FILE_NUMBER, NAME from v$asm_alias
  2  group by GROUP_NUMBER, FILE_NUMBER, NAME;

GROUP_NUMBER FILE_NUMBER NAME
------------ ----------- ----------------------------------------------------------------------
           3         253 REGISTRY.253.805993079
           3         256 users01.dbf
           3         256 users01.dbf.256.806828719
           3         257 system01.dbf
           3         257 system01.dbf.257.807460773
           3         258 sysaux01.dbf
           3         258 sysaux01.dbf.258.807460839
           3         259 example01.dbf
           3         259 example01.dbf.259.807460921
           3  4294967295 ASM
           3  4294967295 DATAFILE
           3  4294967295 ASMPARAMETERFILE

可以看到 system01.dbf 和 system01.dbf.257.807460773 是同一个file的2个alias

其文件号为 257, 257-256=1  则其file directory的记录位于AU=46的 第一个block

[grid@localhost ~]$ kfed read /dev/asm-diski  aun=46 blkn=1|less
kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                            4 ; 0x002: KFBTYP_FILEDIR
kfbh.datfmt:                          1 ; 0x003: 0x01
kfbh.block.blk:                     257 ; 0x004: blk=257
kfbh.block.obj:                       1 ; 0x008: file=1
kfbh.check:                  3782876348 ; 0x00c: 0xe17a1cbc
kfbh.fcn.base:                     2055 ; 0x010: 0x00000807
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kfffdb.node.incarn:           807460773 ; 0x000: A=1 NUMM=0x18106fd2
kfffdb.node.frlist.number:   4294967295 ; 0x004: 0xffffffff
kfffdb.node.frlist.incarn:            0 ; 0x008: A=0 NUMM=0x0
kfffdb.hibytes:                       0 ; 0x00c: 0x00000000
kfffdb.lobytes:               828383232 ; 0x010: 0x31602000
kfffdb.xtntcnt:                    2373 ; 0x014: 0x00000945
kfffdb.xtnteof:                    2373 ; 0x018: 0x00000945
kfffdb.blkSize:                    8192 ; 0x01c: 0x00002000
kfffdb.flags:                        17 ; 0x020: O=1 S=0 S=0 D=0 C=1 I=0 R=0 A=0
kfffdb.fileType:                      2 ; 0x021: 0x02
kfffdb.dXrs:                         19 ; 0x022: SCHE=0x1 NUMB=0x3
kfffdb.iXrs:                         19 ; 0x023: SCHE=0x1 NUMB=0x3
kfffdb.dXsiz[0]:             4294967295 ; 0x024: 0xffffffff
kfffdb.dXsiz[1]:                      0 ; 0x028: 0x00000000
kfffdb.dXsiz[2]:                      0 ; 0x02c: 0x00000000
kfffdb.iXsiz[0]:             4294967295 ; 0x030: 0xffffffff
kfffdb.iXsiz[1]:                      0 ; 0x034: 0x00000000
kfffdb.iXsiz[2]:                      0 ; 0x038: 0x00000000
kfffdb.xtntblk:                      63 ; 0x03c: 0x003f
kfffdb.break:                        60 ; 0x03e: 0x003c
kfffdb.priZn:                         0 ; 0x040: KFDZN_COLD
kfffdb.secZn:                         0 ; 0x041: KFDZN_COLD
kfffdb.ub2spare:                      0 ; 0x042: 0x0000
kfffdb.alias[0]:                    160 ; 0x044: 0x000000a0
kfffdb.alias[1]:                      2 ; 0x048: 0x00000002
kfffdb.strpwdth:                      1 ; 0x04c: 0x01
kfffdb.strpsz:                       20 ; 0x04d: 0x14
kfffdb.usmsz:                         0 ; 0x04e: 0x0000
kfffdb.crets.hi:               32983534 ; 0x050: HOUR=0xe DAYS=0xf MNTH=0x2 YEAR=0x7dd
kfffdb.crets.lo:             2651955200 ; 0x054: USEC=0x0 MSEC=0x68 SECS=0x21 MINS=0x27
kfffdb.modts.hi:               32983534 ; 0x058: HOUR=0xe DAYS=0xf MNTH=0x2 YEAR=0x7dd
kfffdb.modts.lo:                      0 ; 0x05c: USEC=0x0 MSEC=0x0 SECS=0x0 MINS=0x0
kfffdb.dasz[0]:                       0 ; 0x060: 0x00
kfffdb.dasz[1]:                       0 ; 0x061: 0x00
kfffdb.dasz[2]:                       0 ; 0x062: 0x00
kfffdb.dasz[3]:                       0 ; 0x063: 0x00
kfffdb.permissn:                      0 ; 0x064: 0x00
kfffdb.ub1spar1:                      0 ; 0x065: 0x00
kfffdb.ub2spar2:                      0 ; 0x066: 0x0000
kfffdb.user.entnum:                   0 ; 0x068: 0x0000
kfffdb.user.entinc:                   0 ; 0x06a: 0x0000
kfffdb.group.entnum:                  0 ; 0x06c: 0x0000
kfffdb.group.entinc:                  0 ; 0x06e: 0x0000
kfffdb.spare[0]:                      0 ; 0x070: 0x00000000
kfffdb.spare[1]:                      0 ; 0x074: 0x00000000
kfffdb.spare[2]:                      0 ; 0x078: 0x00000000
kfffdb.spare[3]:                      0 ; 0x07c: 0x00000000
kfffdb.spare[4]:                      0 ; 0x080: 0x00000000
kfffdb.spare[5]:                      0 ; 0x084: 0x00000000
kfffdb.spare[6]:                      0 ; 0x088: 0x00000000
kfffdb.spare[7]:                      0 ; 0x08c: 0x00000000
kfffdb.spare[8]:                      0 ; 0x090: 0x00000000
kfffdb.spare[9]:                      0 ; 0x094: 0x00000000
kfffdb.spare[10]:                     0 ; 0x098: 0x00000000
kfffdb.spare[11]:                     0 ; 0x09c: 0x00000000
kfffdb.usm:                             ; 0x0a0: length=0
kfffde[0].xptr.au:                  365 ; 0x4a0: 0x0000016d
kfffde[0].xptr.disk:                  3 ; 0x4a4: 0x0003
kfffde[0].xptr.flags:                 0 ; 0x4a6: L=0 E=0 D=0 S=0
kfffde[0].xptr.chk:                  69 ; 0x4a7: 0x45
kfffde[1].xptr.au:                  368 ; 0x4a8: 0x00000170
kfffde[1].xptr.disk:                  1 ; 0x4ac: 0x0001
kfffde[1].xptr.flags:                 0 ; 0x4ae: L=0 E=0 D=0 S=0
kfffde[1].xptr.chk:                  90 ; 0x4af: 0x5a
kfffde[2].xptr.au:                  368 ; 0x4b0: 0x00000170
kfffde[2].xptr.disk:                  2 ; 0x4b4: 0x0002
kfffde[2].xptr.flags:                 0 ; 0x4b6: L=0 E=0 D=0 S=0
kfffde[2].xptr.chk:                  89 ; 0x4b7: 0x59
kfffde[3].xptr.au:                  368 ; 0x4b8: 0x00000170
kfffde[3].xptr.disk:                  0 ; 0x4bc: 0x0000
kfffde[3].xptr.flags:                 0 ; 0x4be: L=0 E=0 D=0 S=0
kfffde[3].xptr.chk:                  91 ; 0x4bf: 0x5b
kfffde[4].xptr.au:                  366 ; 0x4c0: 0x0000016e
kfffde[4].xptr.disk:                  3 ; 0x4c4: 0x0003
kfffde[4].xptr.flags:                 0 ; 0x4c6: L=0 E=0 D=0 S=0
kfffde[4].xptr.chk:                  70 ; 0x4c7: 0x46
kfffde[5].xptr.au:                  369 ; 0x4c8: 0x00000171
kfffde[5].xptr.disk:                  1 ; 0x4cc: 0x0001
kfffde[5].xptr.flags:                 0 ; 0x4ce: L=0 E=0 D=0 S=0

kfffde[0].xptr.au:                  365 ; 0x4a0: 0x0000016d
kfffde[0].xptr.disk:                  3 ; 0x4a4: 0x0003
kfffde[0].xptr.flags:                 0 ; 0x4a6: L=0 E=0 D=0 S=0
kfffde[0].xptr.chk:                  69 ; 0x4a7: 0x45
kfffde[1].xptr.au:                  368 ; 0x4a8: 0x00000170
kfffde[1].xptr.disk:                  1 ; 0x4ac: 0x0001

则该system01.dbf.257.807460773的前2个extent
指向 disk number=3 的aun=365 和 disknum=1 的aun=368

用X$KFFXP来验证一下

select disk_kffxp, AU_kffxp, xnum_kffxp
from x$kffxp
where group_kffxp=3    -- group number 
and number_kffxp=257   -- file number

DISK_KFFXP   AU_KFFXP XNUM_KFFXP
---------- ---------- ----------
         3        365          0 
         1        368          0 
.......................

 

 

 

 

Directly addressed extents

 

来看一个大于500MB 的ASM上的数据文件的情况,sysaux01.dbf.258.807460839的 file number=258 大小为780M

 

 

SQL> select bytes/1024/1024 ,file_number from v$asm_file;

BYTES/1024/1024 FILE_NUMBER
--------------- -----------
     .001464844         253
     426.257813         256
     790.007813         257
     780.007813         258
     341.257813         259

select disk_kffxp, AU_kffxp, xnum_kffxp
from x$kffxp
where group_kffxp=3
and number_kffxp=258;

DISK_KFFXP   AU_KFFXP XNUM_KFFXP
---------- ---------- ----------
         0        963          0 
         1        962          0 
         2        962          0 
         2        963          1
         0        964          1
         3        958          1
         1        963          2
         3        959          2
         0        965          2
......................................
......................................
         0       1549        780
         1       1548        780
         2       1547        780
         0        978 2147483648
         3        973 2147483648
         1        977 2147483648

2346 rows selected.

 

 

共有2346个extent分配给该数据文件,来看一下该数据文件的directory entry

 

 

[grid@localhost ~]$ kfed read /dev/asm-diski aun=46 blkn=2|less
kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                            4 ; 0x002: KFBTYP_FILEDIR
kfbh.datfmt:                          1 ; 0x003: 0x01
kfbh.block.blk:                     258 ; 0x004: blk=258
kfbh.block.obj:                       1 ; 0x008: file=1
kfbh.check:                  1890402582 ; 0x00c: 0x70ad4116
kfbh.fcn.base:                     2882 ; 0x010: 0x00000b42
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kfffdb.node.incarn:           807460839 ; 0x000: A=1 NUMM=0x18106ff3
kfffdb.node.frlist.number:   4294967295 ; 0x004: 0xffffffff
kfffdb.node.frlist.incarn:            0 ; 0x008: A=0 NUMM=0x0
kfffdb.hibytes:                       0 ; 0x00c: 0x00000000
kfffdb.lobytes:               817897472 ; 0x010: 0x30c02000
kfffdb.xtntcnt:                    2343 ; 0x014: 0x00000927
kfffdb.xtnteof:                    2343 ; 0x018: 0x00000927
kfffdb.blkSize:                    8192 ; 0x01c: 0x00002000
kfffdb.flags:                        17 ; 0x020: O=1 S=0 S=0 D=0 C=1 I=0 R=0 A=0
kfffdb.fileType:                      2 ; 0x021: 0x02
kfffdb.dXrs:                         19 ; 0x022: SCHE=0x1 NUMB=0x3
kfffdb.iXrs:                         19 ; 0x023: SCHE=0x1 NUMB=0x3
kfffdb.dXsiz[0]:             4294967295 ; 0x024: 0xffffffff
kfffdb.dXsiz[1]:                      0 ; 0x028: 0x00000000
kfffdb.dXsiz[2]:                      0 ; 0x02c: 0x00000000
kfffdb.iXsiz[0]:             4294967295 ; 0x030: 0xffffffff
kfffdb.iXsiz[1]:                      0 ; 0x034: 0x00000000
kfffdb.iXsiz[2]:                      0 ; 0x038: 0x00000000
kfffdb.xtntblk:                      63 ; 0x03c: 0x003f
kfffdb.break:                        60 ; 0x03e: 0x003c
kfffdb.priZn:                         0 ; 0x040: KFDZN_COLD
kfffdb.secZn:                         0 ; 0x041: KFDZN_COLD
kfffdb.ub2spare:                      0 ; 0x042: 0x0000
kfffdb.alias[0]:                    161 ; 0x044: 0x000000a1
kfffdb.alias[1]:                      3 ; 0x048: 0x00000003
kfffdb.strpwdth:                      1 ; 0x04c: 0x01
kfffdb.strpsz:                       20 ; 0x04d: 0x14
kfffdb.usmsz:                         0 ; 0x04e: 0x0000
kfffdb.crets.hi:               32983534 ; 0x050: HOUR=0xe DAYS=0xf MNTH=0x2 YEAR=0x7dd
kfffdb.crets.lo:             2724658176 ; 0x054: USEC=0x0 MSEC=0x1bf SECS=0x26 MINS=0x28
kfffdb.modts.hi:               32983534 ; 0x058: HOUR=0xe DAYS=0xf MNTH=0x2 YEAR=0x7dd
kfffdb.modts.lo:                      0 ; 0x05c: USEC=0x0 MSEC=0x0 SECS=0x0 MINS=0x0
kfffdb.dasz[0]:                       0 ; 0x060: 0x00
kfffdb.dasz[1]:                       0 ; 0x061: 0x00
kfffdb.dasz[2]:                       0 ; 0x062: 0x00
kfffdb.dasz[3]:                       0 ; 0x063: 0x00
kfffdb.permissn:                      0 ; 0x064: 0x00
kfffdb.ub1spar1:                      0 ; 0x065: 0x00
kfffdb.ub2spar2:                      0 ; 0x066: 0x0000
kfffdb.user.entnum:                   0 ; 0x068: 0x0000
kfffdb.user.entinc:                   0 ; 0x06a: 0x0000
kfffdb.group.entnum:                  0 ; 0x06c: 0x0000
kfffdb.group.entinc:                  0 ; 0x06e: 0x0000
kfffdb.spare[0]:                      0 ; 0x070: 0x00000000
kfffdb.spare[1]:                      0 ; 0x074: 0x00000000
kfffdb.spare[2]:                      0 ; 0x078: 0x00000000
kfffdb.spare[3]:                      0 ; 0x07c: 0x00000000
kfffdb.spare[4]:                      0 ; 0x080: 0x00000000
kfffdb.spare[5]:                      0 ; 0x084: 0x00000000
kfffdb.spare[6]:                      0 ; 0x088: 0x00000000
kfffdb.spare[7]:                      0 ; 0x08c: 0x00000000
kfffdb.spare[8]:                      0 ; 0x090: 0x00000000
kfffdb.spare[9]:                      0 ; 0x094: 0x00000000
kfffdb.spare[10]:                     0 ; 0x098: 0x00000000
kfffdb.spare[11]:                     0 ; 0x09c: 0x00000000
kfffdb.usm:                             ; 0x0a0: length=0
kfffde[0].xptr.au:                  963 ; 0x4a0: 0x000003c3

kfffdb.xtntblk:                      63 ; 0x03c: 0x003f  //63 extents described in this
kfffdb.break:                        60 ; 0x03e: 0x003c  // file directory block
kfffdb.alias[0]  ALIAS_INDEX

 

 

 

kfffdb.xtntblk=63 说明共有63个extent pointer指针,从kfffde[0].xptr.au到kfffde[59].xptr.au是60个直接盘区指针 direct extent pointer。

 

 

Indirectly addressed extents (kffixe structure)

 

kfffde[60].xptr.au指向剩下的文件目录信息, 这样查看。 kffixe 即是KFBTYP_INDIRECT 间接地址盘区Indirectly addressed extents块,与kfffde结构类似

 

 

[grid@localhost ~]$ kfed read /dev/asm-diski  aun=46 blkn=2|egrep "xptr.au|xptr.disk"

kfffde[60].xptr.au:                 978 ; 0x680: 0x000003d2
kfffde[60].xptr.disk:                 0 ; 0x684: 0x0000
kfffde[61].xptr.au:                 973 ; 0x688: 0x000003cd
kfffde[61].xptr.disk:                 3 ; 0x68c: 0x0003
kfffde[62].xptr.au:                 977 ; 0x690: 0x000003d1
kfffde[62].xptr.disk:                 1 ; 0x694: 0x0001

  1* select path,disk_number from v$asm_disk where group_number=3
SQL> /

PATH                 DISK_NUMBER
-------------------- -----------
/dev/asm-diskj                 3
/dev/asm-diski                 2
/dev/asm-diskh                 1
/dev/asm-diskg                 0

[grid@localhost ~]$ kfed read /dev/asm-diskg aun=978 blkn=0|less
kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                           12 ; 0x002: KFBTYP_INDIRECT
kfbh.datfmt:                          1 ; 0x003: 0x01
kfbh.block.blk:              2147483648 ; 0x004: blk=0 (indirect)
kfbh.block.obj:                     258 ; 0x008: file=258
kfbh.check:                  2166327859 ; 0x00c: 0x811f8a33
kfbh.fcn.base:                     2244 ; 0x010: 0x000008c4
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kffixb.dxsn:                         20 ; 0x000: 0x00000014
kffixb.xtntblk:                     480 ; 0x004: 0x01e0
kffixb.dXrs:                         19 ; 0x006: SCHE=0x1 NUMB=0x3
kffixb.ub1spare:                      0 ; 0x007: 0x00
kffixb.ub4spare:                      0 ; 0x008: 0x00000000
kffixe[0].xptr.au:                  979 ; 0x00c: 0x000003d3
kffixe[0].xptr.disk:                  0 ; 0x010: 0x0000
kffixe[0].xptr.flags:                 0 ; 0x012: L=0 E=0 D=0 S=0
kffixe[0].xptr.chk:                 250 ; 0x013: 0xfa
kffixe[1].xptr.au:                  977 ; 0x014: 0x000003d1
kffixe[1].xptr.disk:                  2 ; 0x018: 0x0002
kffixe[1].xptr.flags:                 0 ; 0x01a: L=0 E=0 D=0 S=0
kffixe[1].xptr.chk:                 250 ; 0x01b: 0xfa
kffixe[2].xptr.au:                  974 ; 0x01c: 0x000003ce
kffixe[2].xptr.disk:                  3 ; 0x020: 0x0003

[grid@localhost ~]$ kfed read /dev/asm-diskj aun=973 blkn=0|less
kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                           12 ; 0x002: KFBTYP_INDIRECT
kfbh.datfmt:                          1 ; 0x003: 0x01
kfbh.block.blk:              2147483648 ; 0x004: blk=0 (indirect)
kfbh.block.obj:                     258 ; 0x008: file=258
kfbh.check:                  2166327859 ; 0x00c: 0x811f8a33
kfbh.fcn.base:                     2244 ; 0x010: 0x000008c4
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kffixb.dxsn:                         20 ; 0x000: 0x00000014
kffixb.xtntblk:                     480 ; 0x004: 0x01e0
kffixb.dXrs:                         19 ; 0x006: SCHE=0x1 NUMB=0x3
kffixb.ub1spare:                      0 ; 0x007: 0x00
kffixb.ub4spare:                      0 ; 0x008: 0x00000000
kffixe[0].xptr.au:                  979 ; 0x00c: 0x000003d3
kffixe[0].xptr.disk:                  0 ; 0x010: 0x0000
kffixe[0].xptr.flags:                 0 ; 0x012: L=0 E=0 D=0 S=0
kffixe[0].xptr.chk:                 250 ; 0x013: 0xfa
kffixe[1].xptr.au:                  977 ; 0x014: 0x000003d1
kffixe[1].xptr.disk:                  2 ; 0x018: 0x0002
kffixe[1].xptr.flags:                 0 ; 0x01a: L=0 E=0 D=0 S=0
kffixe[1].xptr.chk:                 250 ; 0x01b: 0xfa
kffixe[2].xptr.au:                  974 ; 0x01c: 0x000003ce
kffixe[2].xptr.disk:                  3 ; 0x020: 0x0003
kffixe[2].xptr.flags:                 0 ; 0x022: L=0 E=0 D=0 S=0
kffixe[2].xptr.chk:                 228 ; 0x023: 0xe4
kffixe[3].xptr.au:                  978 ; 0x024: 0x000003d2
kffixe[3].xptr.disk:                  2 ; 0x028: 0x0002
kffixe[3].xptr.flags:                 0 ; 0x02a: L=0 E=0 D=0 S=0
kffixe[3].xptr.chk:                 249 ; 0x02b: 0xf9
kffixe[4].xptr.au:                  975 ; 0x02c: 0x000003cf
kffixe[4].xptr.disk:                  3 ; 0x030: 0x0003

kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                           12 ; 0x002: KFBTYP_INDIRECT
kfbh.datfmt:                          1 ; 0x003: 0x01
kfbh.block.blk:              2147483648 ; 0x004: blk=0 (indirect)
kfbh.block.obj:                     258 ; 0x008: file=258
kfbh.check:                  2166327859 ; 0x00c: 0x811f8a33
kfbh.fcn.base:                     2244 ; 0x010: 0x000008c4
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kffixb.dxsn:                         20 ; 0x000: 0x00000014
kffixb.xtntblk:                     480 ; 0x004: 0x01e0
kffixb.dXrs:                         19 ; 0x006: SCHE=0x1 NUMB=0x3
kffixb.ub1spare:                      0 ; 0x007: 0x00
kffixb.ub4spare:                      0 ; 0x008: 0x00000000
kffixe[0].xptr.au:                  979 ; 0x00c: 0x000003d3
kffixe[0].xptr.disk:                  0 ; 0x010: 0x0000
kffixe[0].xptr.flags:                 0 ; 0x012: L=0 E=0 D=0 S=0
kffixe[0].xptr.chk:                 250 ; 0x013: 0xfa
kffixe[1].xptr.au:                  977 ; 0x014: 0x000003d1
kffixe[1].xptr.disk:                  2 ; 0x018: 0x0002
kffixe[1].xptr.flags:                 0 ; 0x01a: L=0 E=0 D=0 S=0
kffixe[1].xptr.chk:                 250 ; 0x01b: 0xfa
kffixe[2].xptr.au:                  974 ; 0x01c: 0x000003ce
kffixe[2].xptr.disk:                  3 ; 0x020: 0x0003
kffixe[2].xptr.flags:                 0 ; 0x022: L=0 E=0 D=0 S=0
kffixe[2].xptr.chk:                 228 ; 0x023: 0xe4
kffixe[3].xptr.au:                  978 ; 0x024: 0x000003d2
kffixe[3].xptr.disk:                  2 ; 0x028: 0x0002
kffixe[3].xptr.flags:                 0 ; 0x02a: L=0 E=0 D=0 S=0
kffixe[3].xptr.chk:                 249 ; 0x02b: 0xf9
kffixe[4].xptr.au:                  975 ; 0x02c: 0x000003cf
kffixe[4].xptr.disk:                  3 ; 0x030: 0x0003

 

 

知识总结

 

  • asm disk的前50个AU(50MB)是为asm metadata保留的
  • ASM 的前255个file number是为metadata file保留的,文件号从1开始, file numner=1的1号文件为ASM的file directory
  • 普通的ASM File的file number从256开始
  • ASM disk的第二个AU即是file number=1的file directory (非必然),在1MB AU和4096 bytes block的情况下可以存放255个file directory information,其block type为KFBTYP_FILEDIR
  • 普通ASM FILE的directory entry的位置,可以这样计算 File number=1的 第 (file number- 256)/256 +2  个extent,blkn=mod(file number-256),256) ,例如文件号 258  =》 第二个extent的blkn=2。
  • KFBTYP_FILEDIR中从kfffde[0].xptr.au到kfffde[59].xptr.au是直接盘区指针 directly extent pointers, kfffde[60].xptr.au以上是KFBTYP_INDIRECT(kffixe)间接盘区指针Indirectly extents pointers。

 

 Indirect Extents

 

由于FILE number 1 中可以存放的extent 指针是有限的,所以对于超过60个extent的文件使用Indirect Extents存放指针。如果需要使用indirect extents,则之后的extent map 记录都记录的是指向indirect extent的指针。

大多数文件仅仅需要一个Indirect Extent,除非文件确实很大。  只能有一级indirection extent,不会有多级。indirect extent中的指针只指向data extent ,不会再指向别的indirect extent 。

 

 

Oracle亚太用户组社区领导人峰会(APOUC)圆满落幕

亚太甲骨文用户组社区进入新阶段

 

北京,20141017 ——

近日,第十届甲骨文亚太用户组社区领导人峰会(Asia Pacific Oracle User Group Community (APOUC) Leaders’ meeting)在香港顺利闭幕,来自中国,日本,泰国,印度等国家的21个用户组25个领军人物齐聚一堂,共同探讨Oracle独立用户组社区的发展状况,同时针对包括JAVA,Database,Application等技术分享相关的最佳实践、创意和经典案例。

会议背景及亮点

  • 凭借在全球范围内拥有超过900个用户组的庞大基数,Oracle用户组社区为所有客户提供了一个包含联络网、信息和最佳实践分享的环境。同时,作为收集信息反馈的关键来源,该社区也帮助甲骨文公司为现有客户提高产品质量、服务水平和综合体验。
  • APOUC的宗旨是为亚太地区Oracle用户组领导人和Oracle之间搭建面对面的沟通桥梁,为用户组社区领导人提供 甲骨文产品和服务的最新资讯,并促进亚太Oracle用户组之间的相互了解和合作。
  • 甲骨文以不同的方式支持其独立用户组社区的发展,甲骨文用户组社区领导人峰会就是其中一种方式。作为一年一次的年度盛会,甲骨文亚太用户组社区领导人峰会同步在亚洲、美洲、欧洲等地区举行,与全球用户大会不同的是,甲骨文亚太用户组社区领导人峰会讨论的内容更加因地制宜,让不同区域的用户对自身所在地区的产品应用更有的放矢,同时能够向其它地区的开发者们学习先进或独特的技术经验。
  • 本次峰会是APOUC阔别香港四年后再次于港举办,会上来自甲骨文香港的市场总监Sylvia Lee向与会嘉宾致欢迎辞。
  • 活动期间,与会者重点探讨了SaaS、移动、物联网、大数据等行业热点话题。同时,甲骨文全球客户计划全球副总裁Tony Banham和iTech 亚太区的Peter Yu分别针对大家关心的Oracle Reference项目和Oracle技术网的ACE项目做了详细讲解。
  • 来自Oracle的用户组团队就用户组和Oracle合作的方式和途径、全球其他地区Oracle用户组的概况和成功实践、未来相关Oracle用户组社区的计划和安排等话题进行了详细介绍。
  • 下午与会者就“Java”以及“Oracle Tech&Apps”两个核心话题进行深入探讨和案例分享。颇受欢迎的“四分钟演讲”环节中有十六位与会者分享其用���组的最佳实践、创新想法和社区故事。
  • 在Java专场中,来自印度、中国大陆、台湾、澳大利亚等Java用户组领导人还介绍了近期围绕Java 8发布而举行的全球Java巡讲活动。该活动于5月来到中国,并于4月30日-10日,分别在北京、广州、上海、南京、杭州举行了7场共创Java未来的活动。来自广东,上海,南京及GreenTea JUG的Java 用户组还于各自城市成功举办了 Java 8的分享和庆祝活动。

甲骨文高管及相关引言

  • 甲骨文公司高级副总裁及首席客户官Jeb Dasteel表示:“Oracle 一直致力于在全球范围建立强大独立的用户组,随着亚太地区近年来经济的迅速发展,亚太地区的用户组社区领导人峰会也日益重要。基于此次大会的分享和领导人们的建议,未来甲骨文会继续积极开发,加大资源共享力度,为开发者带来更多与时俱进并且紧跟当地市场的产品。同时,我们也对甲骨文用户组领导层的辛勤努力表示感谢,并期待更多的用户可以加入我们的社区。”
  • SHOUG主席刘相兵表示,能与亚太地区包括泰国、日本、斯里兰卡、印度的Oracle用户组管理者齐聚一堂,共同探讨Oracle 用户组OUG组织的发展前景与Oracle公司的技术发展则不枉此行。

支持性资源

 

【Oracle ASM】PST Partnership Status Table介绍

Partner and Status Table

相关:https://www.askmac.cn/archives/know-oracle-asm-basic-html.html

一般来说aun=1 是保留给Partner and Status Table(PST)的拷贝使用的。 一般5个ASM DISK将包含一份PST拷贝。多数的PST内容必须相同且验证有效。否则无法判断哪些ASM DISK实际拥有相关数据。

在 PST中每一条记录对应Diskgroup中的一个ASM DISK。每一条记录会对一个ASM disk枚举其partners的ASM DISK。同时会有一个flag来表示该DISK是否是ONLINE可读写的。这些信息对recovery是否能做很重要。

PST表的Blkn=0是PST的header,存放了如下的信息:

  • Timestamp to indicate PST is valid
  • Version number to compare with other PST copies
  • List of disks containing PST copies
  • Bit map for shadow paging updates

PST的最后一个块是heartbeat block,当diskgroup mount时其每3秒心跳更新一次。

如果自己搞不定可以找诗檀软件专业ORACLE数据库修复团队成员帮您恢复!

诗檀软件专业数据库修复团队

服务热线 : 13764045638   QQ号:47079569    邮箱:service@parnassusdata.com

以下为PST header

kfed read /oracleasm/asm-disk01 aun=1 blkn=0 aus=4194304 |less 

kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                           17 ; 0x002: KFBTYP_PST_META
kfbh.datfmt:                          2 ; 0x003: 0x02
kfbh.block.blk:                    1024 ; 0x004: blk=1024
kfbh.block.obj:              2147483648 ; 0x008: disk=0
kfbh.check:                  3813974007 ; 0x00c: 0xe3549ff7
kfbh.fcn.base:                        0 ; 0x010: 0x00000000
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kfdpHdrPairBv1.first.super.time.hi:32999670 ; 0x000: HOUR=0x16 DAYS=0x7 MNTH=0x2 YEAR=0x7de
kfdpHdrPairBv1.first.super.time.lo:1788841984 ; 0x004: USEC=0x0 MSEC=0x3e4 SECS=0x29 MINS=0x1a
kfdpHdrPairBv1.first.super.last:      2 ; 0x008: 0x00000002
kfdpHdrPairBv1.first.super.next:      2 ; 0x00c: 0x00000002
kfdpHdrPairBv1.first.super.copyCnt:   5 ; 0x010: 0x05
kfdpHdrPairBv1.first.super.version:   1 ; 0x011: 0x01
kfdpHdrPairBv1.first.super.ub2spare:  0 ; 0x012: 0x0000
kfdpHdrPairBv1.first.super.incarn:    1 ; 0x014: 0x00000001
kfdpHdrPairBv1.first.super.copy[0]:   0 ; 0x018: 0x0000
kfdpHdrPairBv1.first.super.copy[1]:   1 ; 0x01a: 0x0001
kfdpHdrPairBv1.first.super.copy[2]:   2 ; 0x01c: 0x0002
kfdpHdrPairBv1.first.super.copy[3]:   3 ; 0x01e: 0x0003
kfdpHdrPairBv1.first.super.copy[4]:   4 ; 0x020: 0x0004
kfdpHdrPairBv1.first.super.dtaSz:    15 ; 0x022: 0x000f
kfdpHdrPairBv1.first.asmCompat:186646528 ; 0x024: 0x0b200000
kfdpHdrPairBv1.first.newCopy[0]:      0 ; 0x028: 0x0000
kfdpHdrPairBv1.first.newCopy[1]:      0 ; 0x02a: 0x0000
kfdpHdrPairBv1.first.newCopy[2]:      0 ; 0x02c: 0x0000
kfdpHdrPairBv1.first.newCopy[3]:      0 ; 0x02e: 0x0000
kfdpHdrPairBv1.first.newCopy[4]:      0 ; 0x030: 0x0000
kfdpHdrPairBv1.first.newCopyCnt:      0 ; 0x032: 0x00
kfdpHdrPairBv1.first.contType:        1 ; 0x033: 0x01
kfdpHdrPairBv1.first.spares[0]:       0 ; 0x034: 0x00000000
kfdpHdrPairBv1.first.spares[1]:       0 ; 0x038: 0x00000000
kfdpHdrPairBv1.first.spares[2]:       0 ; 0x03c: 0x00000000
kfdpHdrPairBv1.first.spares[3]:       0 ; 0x040: 0x00000000
kfdpHdrPairBv1.first.spares[4]:       0 ; 0x044: 0x00000000
kfdpHdrPairBv1.first.spares[5]:       0 ; 0x048: 0x00000000
kfdpHdrPairBv1.first.spares[6]:       0 ; 0x04c: 0x00000000
kfdpHdrPairBv1.first.spares[7]:       0 ; 0x050: 0x00000000
kfdpHdrPairBv1.first.spares[8]:       0 ; 0x054: 0x00000000
kfdpHdrPairBv1.first.spares[9]:       0 ; 0x058: 0x00000000
kfdpHdrPairBv1.first.spares[10]:      0 ; 0x05c: 0x00000000
kfdpHdrPairBv1.first.spares[11]:      0 ; 0x060: 0x00000000
kfdpHdrPairBv1.first.spares[12]:      0 ; 0x064: 0x00000000
kfdpHdrPairBv1.first.spares[13]:      0 ; 0x068: 0x00000000
kfdpHdrPairBv1.first.spares[14]:      0 ; 0x06c: 0x00000000
kfdpHdrPairBv1.first.spares[15]:      0 ; 0x070: 0x00000000
kfdpHdrPairBv1.first.spares[16]:      0 ; 0x074: 0x00000000
kfdpHdrPairBv1.first.spares[17]:      0 ; 0x078: 0x00000000
kfdpHdrPairBv1.first.spares[18]:      0 ; 0x07c: 0x00000000
kfdpHdrPairBv1.first.spares[19]:      0 ; 0x080: 0x00000000
  • super.time wall clock time of last PST commit
  • super.last  last committed content version number
  • super.next next available content version number
  • super.copyCnt  # of disks holding PST copies
  • super.version   version of PST header format
  • super.ub2spare  pad to ub4 align
  • super.incarn incarnation of <copy> list
  • super.copy[0]  disks holding the PST copies
  • super.dtaSz  data entries in PST
  • newCopy[0]   new disks holding PST copies
  • newCopyCnt  new # disks holding PST copies

以下为PST table block:

kfed read /oracleasm/asm-disk02 aun=1 blkn=3 aus=4194304 |less 

kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                           18 ; 0x002: KFBTYP_PST_DTA
kfbh.datfmt:                          2 ; 0x003: 0x02
kfbh.block.blk:                    1027 ; 0x004: blk=1027
kfbh.block.obj:              2147483649 ; 0x008: disk=1
kfbh.check:                  4204644293 ; 0x00c: 0xfa9dc7c5
kfbh.fcn.base:                        0 ; 0x010: 0x00000000
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kfdpDtaEv1[0].status:               127 ; 0x000: I=1 V=1 V=1 P=1 P=1 A=1 D=1
kfdpDtaEv1[0].fgNum:                  1 ; 0x002: 0x0001
kfdpDtaEv1[0].addTs:         2022663849 ; 0x004: 0x788f66a9
kfdpDtaEv1[0].partner[0]:         49154 ; 0x008: P=1 P=1 PART=0x2
kfdpDtaEv1[0].partner[1]:         49153 ; 0x00a: P=1 P=1 PART=0x1
kfdpDtaEv1[0].partner[2]:         49155 ; 0x00c: P=1 P=1 PART=0x3
kfdpDtaEv1[0].partner[3]:         49166 ; 0x00e: P=1 P=1 PART=0xe
kfdpDtaEv1[0].partner[4]:         49165 ; 0x010: P=1 P=1 PART=0xd
kfdpDtaEv1[0].partner[5]:         49164 ; 0x012: P=1 P=1 PART=0xc
kfdpDtaEv1[0].partner[6]:         49156 ; 0x014: P=1 P=1 PART=0x4
kfdpDtaEv1[0].partner[7]:         49163 ; 0x016: P=1 P=1 PART=0xb
kfdpDtaEv1[0].partner[8]:         10000 ; 0x018: P=0 P=0 PART=0x2710
kfdpDtaEv1[0].partner[9]:             0 ; 0x01a: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[10]:            0 ; 0x01c: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[11]:            0 ; 0x01e: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[12]:            0 ; 0x020: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[13]:            0 ; 0x022: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[14]:            0 ; 0x024: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[15]:            0 ; 0x026: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[16]:            0 ; 0x028: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[17]:            0 ; 0x02a: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[18]:            0 ; 0x02c: P=0 P=0 PART=0x0
kfdpDtaEv1[0].partner[19]:            0 ; 0x02e: P=0 P=0 PART=0x0
kfdpDtaEv1[1].status:               127 ; 0x030: I=1 V=1 V=1 P=1 P=1 A=1 D=1
kfdpDtaEv1[1].fgNum:                  2 ; 0x032: 0x0002
kfdpDtaEv1[1].addTs:         2022663849 ; 0x034: 0x788f66a9
kfdpDtaEv1[1].partner[0]:         49155 ; 0x038: P=1 P=1 PART=0x3
kfdpDtaEv1[1].partner[1]:         49152 ; 0x03a: P=1 P=1 PART=0x0
kfdpDtaEv1[1].partner[2]:         49154 ; 0x03c: P=1 P=1 PART=0x2
kfdpDtaEv1[1].partner[3]:         49166 ; 0x03e: P=1 P=1 PART=0xe
kfdpDtaEv1[1].partner[4]:         49157 ; 0x040: P=1 P=1 PART=0x5
kfdpDtaEv1[1].partner[5]:         49156 ; 0x042: P=1 P=1 PART=0x4
kfdpDtaEv1[1].partner[6]:         49165 ; 0x044: P=1 P=1 PART=0xd
kfdpDtaEv1[1].partner[7]:         49164 ; 0x046: P=1 P=1 PART=0xc
kfdpDtaEv1[1].partner[8]:         10000 ; 0x048: P=0 P=0 PART=0x2710
kfdpDtaEv1[1].partner[9]:             0 ; 0x04a: P=0 P=0 PART=0x0
kfdpDtaEv1[1].partner[10]:            0 ; 0x04c: P=0 P=0 PART=0x0
kfdpDtaEv1[1].partner[11]:            0 ; 0x04e: P=0 P=0 PART=0x0
kfdpDtaEv1[1].partner[12]:            0 ; 0x050: P=0 P=0 PART=0x0
kfdpDtaEv1[1].partner[13]:            0 ; 0x052: P=0 P=0 PART=0x0
kfdpDtaEv1[1].partner[14]:            0 ; 0x054: P=0 P=0 PART=0x0
kfdpDtaEv1[1].partner[15]:            0 ; 0x056: P=0 P=0 PART=0x0
kfdpDtaEv1[1].partner[16]:            0 ; 0x058: P=0 P=0 PART=0x0
  • kfdpDtaEv1[0].status: 127 ; 0×000: I=1 V=1 V=1 P=1 P=1 A=1 D=1 disk status
  • fgNum   fail group number
  • addTs   timestamp of the addition to the diskgroup
  • kfdpDtaEv1[0].partner[0]:         49154 ; 0×008: P=1 P=1 PART=0×2  partner list

aun=1 的最后第二个block中备份了一份KFBTYP_DISKHEAD

[oracle@mlab2 hzy]$ kfed read /oracleasm/asm-disk02 aun=1 blkn=1022 aus=4194304 |less  
kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                            1 ; 0x002: KFBTYP_DISKHEAD
kfbh.datfmt:                          1 ; 0x003: 0x01
kfbh.block.blk:                    1022 ; 0x004: blk=1022
kfbh.block.obj:              2147483649 ; 0x008: disk=1
kfbh.check:                  3107059260 ; 0x00c: 0xb931f63c
kfbh.fcn.base:                        0 ; 0x010: 0x00000000
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kfdhdb.driver.provstr:         ORCLDISK ; 0x000: length=8
kfdhdb.driver.reserved[0]:            0 ; 0x008: 0x00000000
kfdhdb.driver.reserved[1]:            0 ; 0x00c: 0x00000000
kfdhdb.driver.reserved[2]:            0 ; 0x010: 0x00000000
kfdhdb.driver.reserved[3]:            0 ; 0x014: 0x00000000
kfdhdb.driver.reserved[4]:            0 ; 0x018: 0x00000000
kfdhdb.driver.reserved[5]:            0 ; 0x01c: 0x00000000
kfdhdb.compat:                186646528 ; 0x020: 0x0b200000
kfdhdb.dsknum:                        1 ; 0x024: 0x0001
kfdhdb.grptyp:                        3 ; 0x026: KFDGTP_HIGH
kfdhdb.hdrsts:                        3 ; 0x027: KFDHDR_MEMBER
kfdhdb.dskname:              DATA1_0001 ; 0x028: length=10
kfdhdb.grpname:                   DATA1 ; 0x048: length=5
kfdhdb.fgname:               DATA1_0001 ; 0x068: length=10
kfdhdb.capname:                         ; 0x088: length=0
kfdhdb.crestmp.hi:             32999670 ; 0x0a8: HOUR=0x16 DAYS=0x7 MNTH=0x2 YEAR=0x7de
kfdhdb.crestmp.lo:           1788720128 ; 0x0ac: USEC=0x0 MSEC=0x36d SECS=0x29 MINS=0x1a
kfdhdb.mntstmp.hi:             32999670 ; 0x0b0: HOUR=0x16 DAYS=0x7 MNTH=0x2 YEAR=0x7de
kfdhdb.mntstmp.lo:           1812990976 ; 0x0b4: USEC=0x0 MSEC=0x3 SECS=0x1 MINS=0x1b
kfdhdb.secsize:                     512 ; 0x0b8: 0x0200
kfdhdb.blksize:                    4096 ; 0x0ba: 0x1000
kfdhdb.ausize:                  4194304 ; 0x0bc: 0x00400000

AUN=1 的最后一个block为KFBTYP_HBEAT 心跳表:

[oracle@mlab2 hzy]$ kfed read /oracleasm/asm-disk02 aun=1 blkn=1023 aus=4194304 |less  
kfbh.endian:                          1 ; 0x000: 0x01
kfbh.hard:                          130 ; 0x001: 0x82
kfbh.type:                           19 ; 0x002: KFBTYP_HBEAT
kfbh.datfmt:                          2 ; 0x003: 0x02
kfbh.block.blk:                    2047 ; 0x004: blk=2047
kfbh.block.obj:              2147483649 ; 0x008: disk=1
kfbh.check:                  1479766671 ; 0x00c: 0x5833728f
kfbh.fcn.base:                        0 ; 0x010: 0x00000000
kfbh.fcn.wrap:                        0 ; 0x014: 0x00000000
kfbh.spare1:                          0 ; 0x018: 0x00000000
kfbh.spare2:                          0 ; 0x01c: 0x00000000
kfdpHbeatB.instance:                  1 ; 0x000: 0x00000001
kfdpHbeatB.ts.hi:              32999734 ; 0x004: HOUR=0x16 DAYS=0x9 MNTH=0x2 YEAR=0x7de
kfdpHbeatB.ts.lo:            3968041984 ; 0x008: USEC=0x0 MSEC=0xe1 SECS=0x8 MINS=0x3b
kfdpHbeatB.rnd[0]:           1065296177 ; 0x00c: 0x3f7f2131
kfdpHbeatB.rnd[1]:            857037208 ; 0x010: 0x33155998
kfdpHbeatB.rnd[2]:           2779184235 ; 0x014: 0xa5a6fc6b
kfdpHbeatB.rnd[3]:           2660793989 ; 0x018: 0x9e987e85
  • kfdpHbeatB.instance   instance id
  • kfdpHbeatB.ts.hi timestamp
  • kfdpHbeatB.rnd[0]  随机加盐
  •  External Redundancy一般有一个PST
  • Normal Redundancy至多有个3个PST
  • High Redundancy 至多有5个PST

如下场景中PST 可能被重定位:

  • 存有PST的ASM DISK不可用了(当ASM启东时)
  • ASM DISK OFFLINE了
  • 当对PST的读写发生了I/O错误
  • disk被正常DROP了
  •  在读取其他ASM metadata之前会先检查PST
  • 当ASM实例被要求mount diskgroup时,GMON进程会读取diskgroup中所有磁盘去找到和确认PST拷贝
  • 如果他发现有足够的PST,那么会mount diskgroup
  • 之后,PST会被缓存在ASM缓存中,以及GMON的PGA中并使用排他的PT.n.0锁保护
  • 同集群中的其他ASM实例也将缓存PST到GMON的PGA,并使用共享PT.n.o锁保护
  • 仅仅那个持有排他锁的GMON能更新磁盘上的PST信息
  • 每一个ASM DISK上的AUN=1均为PST保留,但只有几个磁盘上真的有PST数据

 

kfbh.endian
kf3.h /*endiannessofwriter*/

Little endian = 1 Big endian = 0

kfbh.hard
kf3.h /*H.A.R.D.magic#andblocksize*/

kfbh.type
kf3.h /* metadata block type */

kfbh.datfmt
kf3.h /*metadatablockdataformat */

kfbh.block
kf3.h /*blocklocationofthisblock */

blk — Disk header should have T=0 and NUMB=0x0

obj — Disk header should have TYPE=0x8 NUMB=<disknumber> blkandobjvaluesarederivedfromaseriesofmacrosinkf3.h. See “KFBL Macros” in kf3.h for more information.

kfbh.check
kf3.h /*checkvaluetoverifyconsistency*/

kfbh.fcn
kf3.h /*changenumberoflastchange */

kfdpHdrB.time.hi
kf3.h HiorderedbitsfromthelastcommittedPSTupdate

kfdpHdrB.time.lo
kf3.h LoworderedbitsfromthelastcommittedPSTupdate

kfdpHdrB.last
kf3.h /* last version number */

kfdpHdrB.next
kf3.h /* next version number */

kfdpHdrB.copyCnt
kf3.h /* # of PST copies */

This defaults to “1” for external redundancy, “3” for normal redundancy and”5″forhighredundancy. Ifthenumberoffailuregroupsisless than the default value, the number failure groups is the value used.

kfdpHdrB.incarn
kf3.h /* incarnation of <copy> */

This is set to kfdpHdrB.last when the PST is moved to another disk.

kfdpHdrB.copy[0-4]
kf3.h /* disks holding the PST copies */

[0] — external redundancy [0-2] –normalredundancy [0-4] –highredundancy

kfdpHdrB.dtaSz
kf3.h /*#dtaentriesinPST */

This is the number of disks that it needs to keep track of. ub1[0-4027]

 

 

也可以参考ASM HANDS-ON TRAINING
Lab 6 Looking at The Partnership Status Metadata

 

MySQL InnoDB存储引擎表损坏恢复指南

目的

故障排除步骤

适用于:

MySQL服务器版本
5.0至5.7[5.0版到5.7]

 

A 第一反应

A.1 停止,备份,重启

  1. 停止MySQL 服务器。如果它已经下线或崩溃,跳到步骤 2。

代码:

 

/etc/init.d/mysqld stop

 

这里的目的是要冻结数据和表文件的当前状态,这样就没有新的写入发生,并且我们能创建文件副本,而无需注意文件更改会导致数据不一致,或存储信息的丢失。

 

2.如果不是整个MySQL数据目录,备份您的数据和日志文件。

代码:

 

mkdir /root/innodb.bak (or backup path of your choice)
cd /var/lib/mysql (or alternate data directory, if con figured)
dd if=ibdata1 of=ibdata1.bak conv=noerror
cp -p ./ibdata* /root/innodb.bak/
cp -p ./ib_log* /root/innodb.bak/

首先,你创建了存放任何文件副本的目录,然后你在/var/lib/mysql(或你的数据目录)中创建了ibdata1 文件的本地备份,还有ibdata和ib_logfiles的备份到你的备份目录。我喜欢同时使用dd和cp创建(多个)ibdata文件的副本,因为两个工具的性质不同。 Dd工具复制原始文件,而CP复制文件内容到一个新的文件。我没有遇到过任何情况中这是恢复成功的关键,但这仍是我的习惯,我认为这绝不是一个坏习惯。

 

理想情况下,特别当你还没有备份时,如果可能的话,你最好立即尝试创建你的数据目录的完整副本。

命令:

 

cp -Rp /var/lib/mysql{,.orig}

 

我知道这可能过于费时或对一些的紧急情况不太实际,因此,如果这不可行,至少数据文件和InnoDB数据库目录应该提供一些能回退的数据。

 

3.备份你的InnoDB数据库文件夹

 

假设你没有备份完整的MySQL数据目录,你最好还是确保包含InnoDB表的任何数据库都有各自的备份的文件夹。如果你不知道哪个数据库包含InnoDB表,可以使用像这样的命令检查包含的.ibd文件,并将它们复制到备份文件夹(在这个例子中/root/innodb.bak是额外的目录,如果你的DATADIR不是默认的,则需要在一开始更新变量):

代码:

 

DATADIR=/var/lib/mysql; find $DATADIR -type f -name *.ibd | awk -F/ '{print $(NF-1)}' | sort | uniq |
xargs -I {} cp -Rp $DATADIR/{} /root/innodb.bak

 

4.启动MySQL服务器(如果可以的话)
此时将MySQL重新联网是安全的,如果你能这样做而不导致崩溃。如果你能使其联网,接下来就启动MySQL服务,然后执行mysqldump,我建议如下(你可以将这些转储至/root以外的其他路径,如果你愿意记得你的选择):

 

 

Code:

/etc/init.d/mysql start
mysqldump --single-tran saction -AER > /root/dump_wtrans.sql
mysqldump -AER > /root/dump.sql

 

Dumping it with singletransaction flag creates the dump in, go figure, a single transaction, which prevents locking on the database, and may help if you’re running a 100% InnoDB environment so to be safe, particularly if you’re not sure, I recommend running both.

 

以singletransaction标识转储它在单个事务转储数据,go figure,这能防止在数据库上的锁,如果你在运行100% InnoDB环境也会安全,特别是你不能确定的情况下,我推荐两个都运行。

 

一定要检查你的SQL转储内容,以确保数据实际存在。有一些情况中,如果数据由于任何原因无法访问,那只有表结构会存在。尤其当在使用singletransaction,你操作的数据库经常运行ALTER TABLE命令的时候。如果在一个表中mysqldump与ALTER TABLE一致,可能只有结构。 (详细讨论在MySQL的错误报告#71017(BUG17862905))

 

注意:如果你在处理文件系统损坏,尝试并将这些文件备份到另一个可用的磁盘驱动(如果可以,甚至备份到一个安全的远程主机上)

 

A.2 如果MySQL崩溃

 

如果MySQL崩溃并拒绝重启,那这很可能是你此时最关心的问题。当然你在想让它在线用于生产,但最重要的是,MySQL在线可以让你得到真正的MySQL数据转储,这样可以最大限度地减少永久丢失数据的机会,并有助于修复可能损坏的表。

 

由于InnoDB的ACID合规性(MySQL的:: MySQL 5.6参考手册:: 14.2.1 MySQL和ACID模型),它坚持严格的数据一致性标准。这实际上意味着,如果它遇到数据的任何问题,它遵循严格的数据一致性标准。这实质上意味着,如果遇到数据的任何问题,它几乎总是使MySQL崩溃以防止进一步的一致性问题。从理论上讲,这是一件好事,但实际上,非计划的停机时间从来都不是一件好事。

不过使用innodb_force_recovery选项通常可以帮助至少让MySQL回到可访问状态。也就是说,了解它的运行原因,以及如何小心使用它是个好主意。

 

使用 innodb_force_recovery

 

当 InnoDB遇到问题时,它已经尝试默认下的基本恢复步骤,但更多的时候,你需要在你的/etc/my.cnf文件这添加innodb_force_recovery设置来帮助它。这指示InnoDB在恢复模式下启动,告诉它跳过InnoDB启动过程中,通常是崩溃发生的各种部分。你最好在一开始设置最低值,1,并且只有在需要时增加,最高值是6。此设置在你的my.cnf文件的[mysqld]部分输入,在示例中显示:

代码:

[mysqld]

innodb_force_recovery = 1

 

你还可以运行以下单行命令来将其自动添加到你的/etc/my.cnf文件的正确部分(在一开始时,将“mode=”变量更改为任何你想用的模式):

代码:

 

mode=1; sed -i "/^\[mysqld\]/{N;s/$/\ninnodb_force_recovery=$mode/}" /etc/my.cnf

 

然后,一旦你准备把你的服务器返回到默认模式,你可以通过以下命令删除innodb_force_recovery行:

代码:

 

sed -i '/innodb_force_recovery/d' /etc/my.cnf

 

此配置选项不应被用作使你的服​​务器联网的长期,或甚至中期的解决方案。如果你的服务器只能在innodb_force_recovery启用时联网,那在你的服务器上还是有需要处理的重要问题。如果innodb_force_recovery被闲置的活动时间过长,在服务器上可能会造成更多的问题,特别当选项设置为高值(将innodb_force_recovery长时间设为6没什么很好的理由)。这种模式完全是暂时的,仅用于恢复的目的。

 

以下是对每种模式的简短概要(每一种模式还复合自身,这意味着更高的值包括所有的低值的功能):

 

  • Mode 1当遇到损坏页时,不使 MySQL 崩溃
  • Mode 2不运行后台操作
  • Mode 3不会尝试回滚事务
  • Mode 4不计算统计数据或应用存储/缓冲的变化
  • Mode 5在启动过程中不查看撤消日志
  • Mode 6在启动时不从重做日志(ib_logfiles)前滚

 

因此,如果你的MySQL服务器以模式3而不是模式2启动,崩溃与事务回滚过程有关是安全的假设。另外,要注意在MySQL5.6.15中,模式4和6将会把MySQL设为只读模式。

 

如果您已经试过所有innodb_force_recovery模式,但仍然由于InnoDB错误崩溃,下一步最好就是尝试并收集有关导致崩溃的原因的其他信息。

 

B 识别问题

InnoDB的问题多种原因,虽然通常用于概括大部分问题的“corruption”术语了常不准确,但试图找出你所面对的具体问题总是一个好主意。

 

B.1 检查日志

如果你怀疑InnoDB表或数据库被损坏,很可能是因为你发现受到损坏的数据,不存在数据,或者MySQL的服务拒绝启动。对于任何一种情况,你要首先查看的是MySQL错误日志。在通常的设置中,这是在/ var/ lib/mysql/中,而文件是你的主机名与.err后缀。

 

这里是拉出日志最后200行的快速命令,如果你不知道主机名,或不想完整输出(如果不是默认的,将数据目录替换为你自己的):

代码:

 

tail -200 /var/lib/mysql/`hostname`.err

 

这执行hostname命令,并使用返回的字符串代替`hostname`,这是在命令行中的反引号的功能。
在这里你可能还会看到几件事情,可以帮助你pin下你遇到的损坏类型,如果有的话。在本指南中,我会涵盖在页损坏,日志序列号问题和数据字典的问题中最常见的三种损坏问题的类型。下面是几个例子,以及它们可能表示什么的说明:

 

B.1.1 页损坏

错误代码:

 

InnoDB: Database page corruption on disk or a failed
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 515891.

 

通常在这之前还有一些信息,你应该注意,因为它可能包含这种损坏发生在哪里的有用信息,但最终这会告诉你,InnoDB看上去认为在引用的页ID上存在页损坏,或者可能只是无法读取文件。

 

这并不一定表示实际损坏,事实上,在某些情况下,这可能只是操作系统损坏它自己的文件缓存的结果。正因为如此,建议创建备份后,在无任何进一步操作之前,重启你的计算机。也就是说,如果重新启动解决了你的问题,你最好确保你的RAM没有问题或者在它的出门途中没问题,因为这是操作系统损坏它自己的文件高速缓存的常见原因之一。这可能是要在尝试任何恢复之前解决的问题,以避免陷入相同问题。

 

如果你不确定,或重启后,你仍怀疑存在损坏,可以运行下面的脚本在所有的.ibd文件执行innochecksum以找出损坏。这对MySQL仍不能成功启动特别有用,因为它在文件上直接运行,而无需MySQL(事实上,如果表空间的检查在服务器上启动,它无法工作):

 

代码:

 

#!/bin/bash
for i in $( ls /var/lib/mysql/*/*.ibd)
do
innochecksum $i
done

 

innochecksum工具查看在表空间文件中的页,并且计算每页的校验。然后,将这些与存储的校验相比,如果有错配就告诉你。如果有,那通常表明页已被损坏。如果没有发现错配,它不会显示任何输出(除非包含v,即详细输出)。

i

如果MySQL是在线且可访问的,你可以使用CHECK TABLE语句,如下所述:

MySQL :: MySQL 5.5 Reference Manual :: 13.7.2.2 CHECK TABLE Syntax

 

B.1.2 InnoDB 的TimeTraveling 和日志序列号错误

代码:

 

mysql: 120901 9:43:55 InnoDB: Error: page 70944 log sequence number 8 1483471899
mysql: InnoDB: is in the future! Current system log sequence number 5 612394935.
mysql: InnoDB: Your database may be corrupt or you may have copied the InnoDB
mysql: InnoDB: tablespace but not the InnoDB log files. See
mysql: InnoDB: [url=http://dev.mysql.com/doc/refman/5.5/en/ forcing-innodb-recovery.html]MySQL ::
MySQL 5.5 Reference Manual :: 14.21.2 Starting InnoDB on a Corrupted Database[/url]

 

 

 

首先,解释一下日志序列号(LSN)是什么。在InnoDB引擎上每发生一个行为,记录被写入“redo”日志文件,通常默认为MySQL数据目录中的ib_logfile0和ib_logfile1。这两个文件有一组大小,(MySQL中5.6.8+中,默认每个48M),记录按顺序被写入这些文件,从第一个日志文件直到结束,然后继续在第二日志文件中进行。一旦它到达第二日志文件(假定只有2默认日志文件被配置在innodb_log_files_in_group可见)的尾部,它重新开始,再次在第一日志文件的开头写入。所有这些记录都有一个相关的LSN。

 

此外,当一个数据库被修改,在该数据库中的特定页面也得到一个相关LSN。两者之间,这些LSN被一起检查,确保操作以正确的顺序执行。LSN本身基本上是一个到日志文件的偏移,且存储在数据库页头中的LSN告诉InnoDB有多少日志需要被刷。

 

在过程中,无论是意外重启,内存问题,文件系统损坏,复制问题,手动更改为InnoDB的文件或其他,这些LSN不再“同步”。无论是否使你的服务器崩溃,这应该被当作合理损坏,通常你需要解决它。

 

B.1.3 数据字典错误

错误代码:

 

 

[ERROR] Table ./database/table has no primary key in InnoDB data dictionary, but has one in MySQL!
InnoDB: Error: table 'database/table'
InnoDB: in InnoDB data dictionary has tablespace id 423,
InnoDB: but tablespace with that id or name does not exi st. Have
InnoDB: you deleted or moved .ibd files?
[ERROR] Cannot find or open table database/table from
the internal data dictionary of InnoDB though the .fr m file for the
table exists. Maybe you have deleted and recreated InnoDB data
files but have forgotten to delete the corresponding .frm file s
of InnoDB tables, or you have moved .frm files to another datab ase?
or, the table contains indexes that this version of the engine
doesn't support.

 

 

稍微解释一下InnoDB数据字典,它存在于系统表空间,本身作为页的特殊集存储在ibdata1文件中(系统表空间总是被引用为“space 0”),它储存InnoDB显式处理的任何表,列,或索引的元信息。这不是结构元件的主要位置,那些是每个InnoDB表的.frm文件中的,然而,它确实含有许多相同信息。

 

在这里,你通常能看到导致这些错误的差异。如果由于某种原因,ibdata1文件被修改,移动,手动更改或替换,你会突然得到一个数据字典,它并不能反映你的文件或数据库结构中有什么。

如果你看过之前的错误描述,你应该知道在ibdata1中(或以其他方式命名)文件中的数据与在单个表空间/.ibd / .frm文件的数据之间有明显的关联。当该关联丢失或损坏,可能会发生不好的情况。所以这像这样的数据字典的错误出现,最常见的原因是有些文件被手动移动或修改。它通常归结为:“数据字典预计这一文件或表空间在这里,但它不在!”,或“.ibd / .frm文件预计此项目在数据字典中,但它不在! “。再次记住,数据字典存储在ibdata文件中,在大多数环境中,就是MySQL数据目录中的ibdata1。

 

B.2 检查错误的表

当问题发生时,日志通常会立即显示,但它们有时会有点模糊。你通常只会被告知有损坏,但不知道哪个表,页或数据库具体受到影响。两个InnoDBrelevant检查表的方法是CHECK TABLE SQL语句,以及innochecksum工具。你要使用的方法取决于一个因素:你的MySQL服务器是在线还是离线。
MySQL正在运行并且能访问?

 

使用 CHECK TABLE。 innochecksum 不检查当前由服务器启动的表空间。

 

MySQL 崩溃或离线?

 

innochecksum 是你的选择。它查看在表空间文件的页,计算每个的校验,并将之与储存的校验值相比。如果不匹配,显然MySQL 会崩溃,损坏或数据更改,所以这是确认表空间中有问题的可靠方法。

 

B.2.1 使用 CHECK TABLE / mysqlcheck

CHECK TABLE 命令,也由mysqlcheck的运用(特别是c标志,然而mysqlcheck默认为这种行为),在许多不同的确认和比较检查中执行,以尝试识别损坏的迹象。CHECK TABLE和mysqlcheck都在MyISAM和InnoDB表执行,但在本文中,我将着重于在InnoDB表的执行。

 

注意mysqlcheck r的REPAIR功能和“REPAIR TABLE”MySQL命令不会在InnoDB表执行;在这里,mysqlcheck主要只用于找出问题而不是解决问题。

 

这是它在内部具体查找的详细内容:

  1. 相应的.ibd表空间文件的存在
  2. Primary索引的一致性
  3. 正确顺序(键的升序)
  4. 唯一约束的完整
  5. 索引条目的计数
  6. 对表中的其他索引重复步骤1-5。
  7. 最终,所有表经过一个Adaptive Hash Index 检查。

 

如果其中任何一个返回不正确或不一致的值,该表可以被标记为损坏。一旦表被标记为损坏,表不能再被使用,直到问题得到解决,或者直到后续表检查确认该问题已不存在。

 

在某些情况下,如果在MySQL遇到问题之前,CHECK TABLE 在 InnoDB 表中发现了这个问题,这可能导致MySQL服务器被关闭,以避免引起其他错误。尽管这可能是件好事,因为它可以帮助你停止任何进一步的损害的发生,但当你决定在InnoDB表运行CHECK TABLE或mysqlcheck时最好要注意到这一点。

 

这不是发现问题是简单损坏或错误的情况。被发现的损坏/错误只会导致索引/表中相应地被标记。

 

运行CHECK TABLE

CHECK TABLE命令必须早MySQL shell中运行,或通过MySQL的其它地方执行。例如,这里是我创建的一个情况,我将现有的dictionary.ibd文件用来自同一个数据库另一个表的.idb文件替换,你可以看到一个普通表,与一个被损坏或有遇到错误表进行CHEACK TABLE的对比:
代码:

 

 

mysql> CHECK TABLE roundcube.users;

+-----------------+-------+-------- --+----------+

| Table | Op | Msg_type | Msg_text |
+-----------------+-------+----------+----------+
| roundcube.users | check | status | OK |
+-----------------+-------+----------+----------+
1 row in set (0.13 sec)



mysql> CHECK TABLE roundcube.dictionary;
+----------------------+-------+-------- --+------------------------------------------------------------
----+
| Tab le | Op | Msg_type |
Msg_text |
+----------------------+-------+----------+--------------------- ---------------------------------------
----+
| roundcube.dictionary | check | Warning | InnoDB: Tablespace is missing for table
'roundcube/dictionary' |
| roundcube.dictionary | check | Error | Table 'roundcube.dictionary' doesn't
| roundcube.dictionary | check | Error | Table 'roundcube.dictionary' doesn't
exist |
| roundcube.dictionary | ch eck | status | Operation
failed |
+----------------------+-------+----------+----------- -------------------------------------------------
----+
3 row s in set (0.00 sec)

 

 

In this situation, the error experienced actually warrants the server being automatically shut down. The instant I ran the CHECK TABLE on roundcube.dictionary the first time, the server crashed. This is because I “introduced” the active MySQL instance to the problem’s existence. 在这种情况下,经历的错误实际保证了服务器被自动关闭。我第一次在roundcube.dictionary上运行CHECK TABLE,服务器崩溃了。这是因为我将主动MySQL实例“带入”到这个问题的存在。

 

InnoDB的数据一致性坚持一旦这样的问题出现,它应尽快被停止。根据引发崩溃的源头,需要不同级别的innodb_force_recovery使MySQL服务器恢复。在缺少表空间的情况下,最低值为1就行了。

 

请记住MySQL服务器被强制崩溃是有原因的。不要通过快速启用innodb_force_recovery立即回到MySQL!这有时会造成比它解决的问题更多的问题。

 

运行 mysqlcheck

 

通常,你要一次检查许多表或数据库。CHECK TABLE对通配符没有任何支持,因此当要检查所有数据库中的表,或检查服务器上的所有数据库时,它就不实用了。 mysqlcheck默认在命令行中执行CHECK TABLE以弥补这点,允许你轻松地检查整个数据库或所有数据库。对数据库执行CHECK TABLE的默认语法是(用你的数据库名替换db_name):

代码:

mysqlcheck db_name

 

 

然后它将输出对数据库中每个表执行CHECK TABLE的结果。如果你只想在一些选出的表上执行命令,你也能在数据库名后指定表 (mysqlcheck db_name tbl1_name tbl2_name…)。

 

下面是我在之前的情况中对roundcube数据库执行命令的例子:

代码:


-bash-4.1# mysqlcheck roundcube

roundcube.cache OK
roundcube.cache_index OK
roundcube.cache_messages OK
roundcube.cache_thread OK
roundcube.contactgroupmembers OK
roundcube.contactgroups OK
roundcube.contacts OK
roundcube.cp_schema_version OK
roundcube.dictionary
Warning : InnoDB: T ablespace is missing for table 'roundcube/dictionary'
Error : Table 'roundcube.dictionary' doesn't exist
status : Operation failed
roundcube.identities
Warning : InnoDB: T ablespace is missing for table 'roundcube/identities'
Error : Table 'roundcube.identities' doesn't exist
status : Operation failed
roundcube.searches OK
roundcube.session OK
roundcube.system OK
roundcube.users OK

 

Additionally, you can use the A flag (or alldatabases) to perform a CHECK TABLE on all tables in all databases on your server. 此外,还可以使用一个标志(或alldatabases)在服务器上的所有数据库中的所有表上 执行CHECK TABLE。

 

B.2.2 使用innochecksum

 

像在之前提到的 ,InnoDB需要有一致的数据,当它遇到对本身校验的不匹配,将立即停止活动的服务器。考虑到这一点,innochecksum不仅可以帮助识别损坏,而且能监控校验状态。这里唯一的缺点,在预防方面,即它不能在任何启动的 表空间文件运行。因此,要得到表的校验状态的描述,服务器需要下线。

 

不过,又有我们处理的是在崩溃的MySQL服务器的损坏,这可能你是最不用担心的,innochecksum在追踪不匹配的校验方面很强大,特别是它不需要服务器在线。

 

从innochecksum得到的输出将由发生的情况变化而变化,一般除非使用-v 指定详细的输出,你不会看到任何输出,除非确实有发现的问题。下面是发现在数据文件中的校验失败的例子:

代码:

 

page 8 invalid (fails old style checksum)
page 8: old style: calculated = 0x 819564 6B; recorded = 0x DA79A2EE

 

innochecksum工具目前只能在专门引用的表空间文件(.ibd)运行,但你可以简单使用find命令如下,在所有.ibd文件(调整合适的DATADIR)执行innochecksum:

代码:

 

DATADIR=/var/lib/mysql; find $DATADIR -type f -name *.ibd -o -name ibdata* | xargs -I{} innochecksum {}

 

C 恢复数据
一旦你确定了问题并准备好你的服务器,下一步将是获得以运作排序的数据。MySQL此时应在线且至少部分响应,无论是通过innodb_force_recovery或其他方式。

 

C.1 MySQL工具/从.frm文件中提取CREATE TABLE语句
MySQL提供可下载的实用工具,包括对特定的恢复过程有帮助的一些工具,其中有个工具叫做“mysqlfrm”。该工具可以简单地从.frm文件中提取表的CREATE TABLE语句。该语句非常有用,因为几乎所有有用的恢复方法能重建你试图修复原始表的结构,而且往往不能有任何MySQL直接访问原始表本身成。

 

C.1.1 下载并安装 MySQL 工具:

此处下载包。

在服务某处提取它。

代码:

 

tar xvzf mysql-utilities*

 

更改到解压目录,将执行权限给setup.py,然后运行它的编译和安装操作

代码:

 

cd mysql-utilities-1.4.3
chmod +x setup.py
./setup.py build
./setup.py insta ll

 

C.1.2 要从.frm文件提取CREATE TABLE语句:

mysqlfrm将根据您现有的安装创建其临时的MySQL守护进程,这意味着如果你现有的MySQL安装已在运行,你需要指定一个备用端口。这里我运行的示例是从我的“staff.frm”文件中提取CREATE TABLE:

代码:

 

mysqlfrm --basedir=/usr --user=mysql --port=3308 /var/lib/mysql/testdb/staff.frm

 

这是之后的输出:

 

代码:


# Spawning server with --user=mysql.
# Starting the spawned server on por t 3308 ... done.
# Reading .frm files
#
# Reading the staff.frm file.
#
# CREATE statement for staff.frm:
#
CREATE TABLE `staff` (
`staff_id` tinyint(3 ) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`address_id` smallint(5) unsigned NOT NULL,
`picture` blob,
`email` varchar (50) DEFAULT NULL,
`store_id` tinyint(3) unsigned NO T NULL,
`active` tinyint(1) NOT NULL DEFAULT '1' ,
`username` varchar(16) NOT NULL,
`password` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CUR RENT_TIMESTAMP,
PRIMARY KEY (`staff_id`),
KEY `idx_fk_store_id` (`s tore_id`),
KEY `idx_fk_address_id` (`address_i d`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
#...done.


以上输出从“CREATE TABLE”部分到“CHARSET= UTF8”都是完整的,需要可执行的CREATE TABLE语句来重建“staff”表和正确的结构。要在MySQL shell中执行,我可以简单地粘贴该完整语句,并用分号(;)结尾。在某些情况下,你也可能需要禁用外键检查使之成功:

 

代码:

 

SET FOREIGN_KEY_CHECKS=0;

 

C.2 损坏的表
如果您已经确定了当前在服务器的损坏的表,根据情节严重程度,你可以有几种方法处理。在几乎所有表损坏的情况下,你至少需要以innodb_force_recovery为1运行的InnoDB,使MySQL在你操作时保持在线。

 

C.2.1 以CREATE..LIKE恢复表
这种方法的目标是尝试使用表的现有结构和数据,由于它们是可访问的,能用来简单地创建一个具有相同的结构和数据的新表来替代原始表。基本步骤如下:

 

1.访问MySQL shell通过运行:

代码:

mysql -u root -p

 

成功的话,你会得到这样的提示符:

mysql>

 

2. 运行以下 MySQL 语句,以你的表和数据库名称分别替换 tablename 和 dbname :

代码:

 

USE dbname;
CREATE TABL E tablename_recovered LIKE tablename;
INSERT INTO tablename_recovered SELECT * FROM ta blename;

 

3. 如果在这里没有遇到任何问题,那你真走运了。此时,你就能删除原始表,并将”_recovered” 表名改回原来的:

 

 

DROP dbname.tablename;
RENAME TABLE dbname.ta blename_recovered TO dbname.tablename;

 

 

当遇到页损坏的情况,这种方法是最简单的,但可能成功率最低,因为它取决于你能否从表中选出所有的数据,并创建一个基于它结构的恢复表。如果没有可访问或可读的,这种方法可能会失败。

 

但是,如果它在“SELECT *”部分失败了,你还有另一个选择,涉及增量插入。因此,选择不执行以上的“INSERT INTO… SELECT*……”,你要执行以下操作:

 

insert ignore into tablename_recovered select * from tablename limit 10;
insert ignore into tablename_recovered select * from tablename limit 50;
insert ignore into tablename_recovered select * from tablename limit 100 ;
insert ignore into tablename_recovered select * from tablename limit 200;

...

 

With this method, you can piece through the data that’s accessible until you reach the point of failure, at which point you’ll likely lose connection from the MySQL server.

使用这种方法,你可以拼凑可访问的数据,直到到达故障点,此时你可能会失去MySQL服务器的连接。

 

 

C.2.2 恢复多个/所有的InnoDB数据库并重建ibdata / ib_log文件

这种方法的成功又取决于mysqldump从每个问题表中生成功能数据的能力,但它也是更全面的方法,因为它涉及到初始化新ibdata和ib_log文件。正因为如此,如不谨慎处理,这种方法也很有可能失败。所以确保你已经运行了第一反应的步骤,且在进一步操作之前有另外的备份。

 

如果你已有备份转储想要恢复从步骤2开始的现有损坏的数据库,也可以使用此方法。

 

1.对所有数据库执行mysqldump

 

mysqldump  -AER > /root/recovery_dump.sql

 

如果你在此处遇到任何错误,停下来仔细看一下错误。如果它们表明任何重要数据都被损坏到无法正确转储的地步,最好就不要继续使用该方法了。此外,一定要查看生成的转储文件,以确保它包含预期的数据。

 

2. 删除所有受影响的 InnoDB 数据库。

 

mysql> SET FOREIGN_KEY_CHECKS=0;
mysql> DROP DATABASE db1;
mysql> DROP DATABASE db2;
...


3. 在禁用 innodb_fast_shutdown 以确保干净,完整的关闭执行后,停止 mysqld。

 

mysql -e "SET GLOBAL innodb_fast_shutdown=0"
/etc/init.d/mysql stop

 

 

4.重新定位 InnoDB 数据并重做日志文件

 

mv /var/lib/mysql/ibdata* /tmp/
mv /var/lib/mysql/ib_log* /tmp/

 

 

5. 注释或删除在当前 /etc/my.cnf 中的 innodb_force_recovery 条目:

 

sed -i '/innodb_force_recovery/d' /etc/my.cnf

 

6. 启动 mysqld 并监控日志,以确保其联网,初始化数据及正确重做日志文件

 

nohup /etc/init.d/mysql start & tail -f /var/lib/mysql/`hostname`.err

 

7.  一旦你确定MySQL仍在线上,并准备将数据导入就恢复转储。

 

mysql  < /root/recovery_dump.sql

 

 

C.3 日志序列号不匹配/在未来(In Future)

 

为了确保你的数据保持一致,并且具有“撤销/重做”的功能,InnoDB在日志文件和表空间文件中保存了日志序列号。每当在InnoDB表中的数据有所变化,它会导致日志序列号更新。这相当于一个偏移,指示InnoDB在文件中要向前或向后查看多少以找到引用该数据的具体状态。

 

在任何时间内,如果发生了什么事导致一个序列号被更新,而其他没有,最终你会在MySQL日志中看到有关“不匹配的日志序列号”或“日志序列号是在未来”的错误。为了你的数据库服务器再次正常工作,使这些序号回到正轨是很重要的。

 

C.3.1 删除并重建数据

这是最有效和唯一的 “实际”的解决方案,但遗憾的是,对许多人来说,这是不适用的,因为在实际情况中,不是每个人得到的数据可用(不过,如果你正在经历,你是该考虑建立一个有效的备份解决方案)。但是,如果你的MySQL实例没有崩溃,而你能创建mysqldump,那它值得一试,并将它重新导入回。你可以按照在损坏的表章节中“还原多个/所有的InnoDB数据库并重建ibdata/ ib_log文件” 方法中的详细步骤,尝试恢复现有数据库的转储。

 

再次声明,在进行任何更改之前,要确保你已经创建了所有重要ibdata,ib_logfile,.ibd,和.frm文件的副本。

 

C.3.2重建ib_logfiles

 

如果你只是处理单个MySQL实例,而不是一个主- >从或其他集群的情况,这可能是一种有效的方法。这里的目的是把现有的ib_logfiles从等式中取出,让MySQL来重新初始化它们来重启。说实话这种方法的成功率有限,但它的使用历史很长,值得一提:

 

mysql -e "SET GLOBAL innodb_fast_shutdown=0"
/etc/init.d/mysql stop
cd /var/lib/mysql
mv ib_logfile0 ib _logfile0.bak
mv ib_logfile1 ib_logfile1.bak
/etc/init.d/mysql start

 

第一个命令确保InnoDB执行干净的关闭,这偶尔会对情况有帮助,值得写在这里。

 

C.3.3 执行引擎交换

 

这又是一个较激进的方法,虽然操作难度大,但根据我个人的经验,它似乎有一个非常稳定的成功率,但它肯定也取决于你的操作环境。这种方法还需要MySQL能被成功启动。

 

1. 将所有数据库中的表从InnoDB转换为MyISAM,在MySQL运行以下命令,将有管数据库名替换db_name:

 

mysql -e "SELECT concat('ALTER TABLE ', TABLE_NAME,' ENGINE=MYISAM;') FROM Information_schema.TABLES WHERE TABLE_SCHEMA = 'db_name' AND ENGINE = 'InnoDB' AND TABLE_TYPE = 'BASE TABLE'"

 

2.停止 MySQL之后,将 ibdata* 和 ib_logfiles 取出:

 

/etc/init.d/mysql stop
mkdir -p /root/innodb.bak
mv ib* /root/innodb.bak/
/etc/init.d/mysql start

 

3.现在,你的 MySQL 启动且其中的表使用 MyISAM,是时候将它们转换回 InnoDB了,祈祷把(再次用你的数据库名替换db_name ):

 

mysql -e "SELECT concat('ALTER TABLE ', TABLE_NAME,' ENGINE=InnoDB;') FROM  Information_schema.TABLES WHERE TABLE_SCHEMA = 'db_name' AND ENGINE = 'MyISAM'"

 

C.4 数据字典问题

 

在这些错误中,最常见的数据字典问题是有关表或表格文件不在InnoDB期望它们的状态,很多时候是由于不当删除InnoDB的.ibd或.frm文件,或者由于删除/移动ibdata文件。了解这些之后,要注意以下几点:

 

C.4.1 如何正确删除.ibd文件

数据库各子目录中的“.ibd文件代表在这些数据库中表的表空间。
删除文件本身会导致许多与InnoDB保持数据一致性的记录相关的问题。如果你由于一些原因(如尝试导入新的表空间/ idb文件)只要删除表空间,正确的方法是使用ALTER TABLE … DISCARD TABLESPACE语句,如:

 

mysql -e "ALTER TABLE roundcube.staff DISCARD TABLESPACE"

 

在上面的例子中,’roundcube’是数据库,’staff’是表。如果你这样做后检查数据库目录,你会发现虽然.frm文件仍然存在,但.ibd文件没了。记住,数据本身仍然显示于服务器上。

 

注:通常在这样操作之前,你需要先停用foreign_key_checks,通过以下操作执行:

 

SET FOREIGN_KEY_CHECKS=0;

 

C.4.2 ibd文件丢失后表的重建

 

如果你已删除或更改表空间(.ibd)文件,你很有可能遇到像这样一个错误:

 

[ERROR] MySQL is trying to open a table handle but the .ibd file for table dbname/tblname does not exist.

 

这个情况是它仍然认为表存在,这表示在该问题被解决之前,你将无法正常重建表。幸运的是,尽管执行失败,InnoDB能聪明地意识到发生了什么,并进行一些实用进程,如果运行以下命令(在适当处替换dbname和tblname):

第一步是尝试删除任何在表空间遗留的一切:

 

ALTER TABLE dbname.tblname DISCARD TABLESPACE;

 

它可能会或不会在MySQL shell报错,但如果你查看错误日志,它仍然继续清除缓冲:

 

InnoDB: Warning: cannot delete tablespace 251 in DISCARD TABLESPACE.
InnoDB: But let us remove the insert buffer entries for this tablesp ace.

 

然后,尝试删除实际表记录(如果你需要保存.frm文件来再次获得CREATE TABLE语句,确保在执行此步骤之前进行复制):

 

DROP TABLE dbname.tblname;

 

你更可能遇到类似的错误,但以下会在日志中再次出现

 

InnoDB: We removed now the InnoDB internal data dictionary entry
InnoDB: of table `dbname/tblname`.

 

之后你就能使用备份或.frm文件副本来重建表(使用之前描述的mysqlfrm方法)。

 

C.4.3 .frm文件存在,但表不存在

 

这是与之前问题的相同的行,但情况更简单,也更容易解决:

代码:

 

InnoDB: Cannot find table test/child2 from the internal data dictionary
InnoDB: of InnoDB though the .frm file for the table exists.

 

这里最常见的问题是,部分运行的删除或修改语句没有导致所有表中的文件被正确删除。在这些情况下,.frm文件可以简单地被安全删除,且InnoDB应该相应调整。我的建议是不要删除它,而是将其复制到备份文件夹,至少是暂时的,这样你就有CREATE TABLE语句,你可以以任何原因访问它。

 

If you did not intend to drop this table, or if the .ibd file was deleted by some other means, then aside from attempting some deep data recovery by digging through the ibdata file your only option in regards to restoring this table would be to restore from a backup, because InnoDB is essentially indicating in the error that this .frm file is absolutely the only thing left of the table in question. Definitely do not delete the .frm file if this is the case simply relocate it so that you can perhaps have a chance of recreating the table and rebuilding your data.

如果你不打算删除该表,或者如果.ibd文件通过其他方式被删除,那么除了通过挖掘ibdata文件尝试一些深层次的数据恢复,你唯一恢复表的方法就是从备份进行恢复,因为InnoDB基本上指明了错误,.frm文件是所剩表中唯一有问题的。如果是这样的话,绝对不要删除.frm文件,而是对它重新定位,这样或许有机会重建表,并重建你数据。

 

C.4.4 孤表或丢失的.frm文件

如果.frm文件因为某些原因丢失,你可能会看到如下所示的错误:

 

InnoDB: Error: table dbname/tblname already exists in InnoDB internal
InnoDB: data dictionary. Have you deleted the .frm file
InnoDB: and not used DROP TABLE? ...

 

在这种情况下,这个错误的说明通常描述了处理该问题最有效的方法:

 

 

InnoDB: You can drop the orphaned table inside InnoDB by
InnoDB: creating an InnoDB table with the same name in a nother
InnoDB: database and moving the .frm file to the current datab ase.
InnoDB: Then MySQL thinks the table exists, and DROP TABLE will
InnoDB: succeed.

 

 

这表示,如果你有孤表的CREATE TABLE语句,不论通过备份或其他方式,你可以创建一个测试数据库,并在其中创建表的副本(仅结构)。这将创建一个.frm文件,它可以用来复制到原始数据库,并替换丢失的.frm,使你能删除表。这里是一个简单的例子,假设原来的数据库和表名都是“test”:

 

代码:

 

# mysql

mysql> CREATE DATABASE test2;
mysql> CREATE TABLE ... CHARS ET=utf8;
mysql> quit
# cp /var/lib/mysql/test2/test.frm /var/lib/mysql/test/
# mysql
mysql> SET FOREIGN_KEY_CHECKS=0;
mysql> DROP TABLE test.test;

 

 

总结

InnoDB的数据一致性标准是一把双刃剑。当小心运作并充分理解它是如何操作时,它就是梦幻般的引擎,但很遗憾,当涉及对它的环境改变时,它就不是最宽容的了。它有一些很好的方法来处理自己的情况,还有一些出色的错误日志记录,但当要确保一个稳定的环境时,它也绝对是需要谨慎操作的。

 

恢复MySQL中损坏的Innodb表

假设你在使用MySQL中的InnoDB表,但是硬件出现问题,或者遇到了驱动程序错误,内核错误,电源故障或某些罕见的MySQL错误,而在InnoDB表空间的某些页被损坏。在这种情况下,Innodb通常打印出如下:

 

InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 7.
InnoDB: You may have to recover from a backup.
080703 23:46:16 InnoDB: Page dump in ascii and hex (16384 bytes):
… A LOT OF HEX AND BINARY DATA…
080703 23:46:16 InnoDB: Page checksum 587461377, prior-to-4.0.14-form checksum 772331632
InnoDB: stored checksum 2287785129, prior-to-4.0.14-form stored checksum 772331632
InnoDB: Page lsn 24 1487506025, low 4 bytes of lsn at page end 1487506025
InnoDB: Page number (if stored to page already) 7,
InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) 6353
InnoDB: Page may be an index page where index id is 0 25556
InnoDB: (index “PRIMARY” of table “test”.”test”)
InnoDB: Database page corruption on disk or a failed

 

MySQL并且崩溃,日志声称故障。 所以你要如何恢复这样的表呢?

被损坏的可能有各种东西,我将详细查看这篇文章中的简单示例 – 在聚集键中索引页被损坏。这相比于在secondary索引的数据损坏更糟,该情况下简单的OPTIMIZE TABLE足以重建它,但它相对于表字典损坏又较好,因为该情况下表的恢复会更难。

在这个例子中,我其实手动编辑了test.ibd 文件,替换了几个字节使得损坏较轻。

首先,注意在INNODB中的CHECK TABLE 没什么用。从手动损坏的表中获得:

 

mysql> check table test;
ERROR 2013 (HY000): Lost connection to MySQL server during query




mysql> check table test;

+-----------+-------+----------+----------+
| Table     | Op    | Msg_type | Msg_text |
+-----------+-------+----------+----------+
| test.test | check | status   | OK       |
+-----------+-------+----------+----------+
1 row in set (0.69 sec)

 

 

在这个例子中,数据损坏只发生在页中,所以一旦你以innodb_force_recovery=1 启动Innodb,你能进行如下操作:首先在正常操作模式下运行check table – 在这样的情况下,如果有校验错误(即使我们运行CHECK操作),Innodb 就直接崩溃了。在第二种情况下,我设置innodb_force_recovery=1 ,你能看到即使在日志文件中获得校验故障的信息,CHECK TABLE 仍显示表没问题。这表示你不能相信Innodb中的CHECK TABLE 来确定表没问题。

 

 

mysql> CREATE TABLE `test2` (->   `c` char(255) DEFAULT NULL,
->   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
->   PRIMARY KEY (`id`)
-> ) ENGINE=MYISAM;
Query OK, 0 rows affected (0.03 sec)




mysql> insert into test2 select * from test;
Query OK, 229376 rows affected (0.91 sec)
Records: 229376  Duplicates: 0  Warnings: 0

 

现在,在MyISAM表中有所有的数据,你只要删除旧表,并在在没有innodb_force_recovery选项下重新启动Innodb后将新表转移回Innodb。你还可以重命名旧表,以便以后能详细查看。另一种方法是用MySQLDump转储表并将它加载回来。这差不多是同样的。我正在使用MyISAM表,随后你会看到原因。

你可能会认为你为什么不干脆用OPTIMIZE TABLE重建表?这是因为在innodb_force_recovery模式下运行,Innodb就只对于数据操作可读,这样就不能插入或删除任何数据(虽然你可以创建或删除InnoDB表):

 

mysql> optimize table test;

+-----------+----------+----------+----------------------------------+
| Table     | Op       | Msg_type | Msg_text                         |
+-----------+----------+----------+----------------------------------+
| test.test | optimize | error    | Got error -1 from storage engine |
| test.test | optimize | status   | Operation failed                 |
+-----------+----------+----------+----------------------------------+
2 rows in set, 2 warnings (0.09 sec)

 

 

我也这样认为,所以我接下来对test.ibd进行了一些编辑,完全删除其中一个页头。现在CHECK TABLE 将会崩溃,即使innodb_force_recovery=1这很简单,对吧?

 

080704 0:22:53 InnoDB: Assertion failure in thread 1158060352 in file btr/btr0btr.c line 3235
InnoDB: Failing assertion: page_get_n_recs(page) > 0 || (level == 0 && page_get_page_no(page) == dict_index_get_page(index))
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even

 

如果你得到这样的故障声明,很可能更高的innodb_force_recovery 值也没什么帮助 – 只有在多个系统区域有损坏的情况下有用,但不能以Innodb处理页数据的方式作什么改变。

接下来是试错的做法:

 

mysql> insert into test2 select * from test;
ERROR 2013 (HY000): Lost connection to MySQL server during query

你可能认为mysql将扫描表直到首先损坏的行并在MyISAM表中获得结果?

 

遗憾的是,test2 在运行后为空的。同时,我看到一些可能被选出的数据。问题是,有一些缓冲发生,而MySQL崩溃时不会将所有能够恢复的数据储存到MyISAM表。

 

手动恢复时,使用一些带有LIMIT的查询更简便:


mysql> insert ignore into test2 select * from test limit 10;
Query OK, 10 rows affected (0.00 sec)
Records: 10  Duplicates: 0  Warnings: 0




mysql> insert ignore into test2 select * from test limit 20;
Query OK, 10 rows affected (0.00 sec)
Records: 20  Duplicates: 10  Warnings: 0




mysql> insert ignore into test2 select * from test limit 100;
Query OK, 80 rows affected (0.00 sec)
Records: 100  Duplicates: 20  Warnings: 0




mysql> insert ignore into test2 select * from test limit 200;
Query OK, 100 rows affected (1.47 sec)
Records: 200  Duplicates: 100  Warnings: 0


mysql> insert ignore into test2 select * from test limit 300;
ERROR 2013 (HY000): Lost connection to MySQL server during query

 

 

注意,即使你不使用MyISAM表,而是获取脚本的数据,在MySQL崩溃时一定要使用LIMIT或PK Rangers,你不会得到所有在网络数据包的数据,由于缓冲你可能得到部分。你能看到,我可以从新的测试的表中获取行,直到最终遇到使MySQL崩溃的行。在这种情况下,我们可以预估在200和300之间有这样的行,我们可以执行一大堆类似的语句,进行“二进制搜索”来查找确切的行号。

所以,现在我们发现在表中损坏的数据,我们需要以某种方式跳过它。为此我们要找到能被恢复的最大PK,并尝试一些更高的值。

 

mysql> select max(id) from test2;

+---------+
| max(id) |
+---------+
|     220 |
+---------+
1 row in set (0.00 sec)




mysql> insert ignore into test2 select * from test where id>250;
ERROR 2013 (HY000): Lost connection to MySQL server during query




mysql> insert ignore into test2 select * from test where id>300;
Query OK, 573140 rows affected (7.79 sec)
Records: 573140  Duplicates: 0  Warnings: 0

 

因此,我们试图跳过30行,太少,跳过80行,还行。再次使用二进制搜索,获知你需要跳过多少行来恢复尽可能多的数据。行大小对你很有用。在这个例子中,每行约280个字节,所以每页有50行,所以30行不够也不令人吃惊 – 通常,如果页目录已损坏,你至少需要跳过整个页面。如果页面在较高层级在BTREE损坏,你可能需要跳过很多页(整个子树)来使用此恢复方法。

你可能需要跳过多个坏页,而不只示例中的一个。

另一个提示 – 你最好CHECK在MySQL崩溃之后用于恢复的MyISAM表,以确保索引没有被损坏。

我们探讨了如何从简单的InnoDB表获得恢复的数据。在更复杂的情况下,你可能需要使用较高的innodb_force_recovery模式来阻止数据清楚,插入缓冲合并或从事务日志进行恢复。虽然说恢复模式越低,恢复过程中越可能得到更好的数据。

在某些情况下,如数据字典或聚类索引的“root页”损坏,此方法将无法很好地运作。在这种情况下,您可能希望使用恢复软件包,它在需要恢复被删除的行或表时也很有帮助。

 

我还要说一下,我们提供MySQL恢复的援助,包括对Innodb损坏和被删除的数据进行恢复。

Oracle DUL(data unloader) 専用データ復旧ツールユーザーズマニュアル

ORACLEデータベースを正常にオープンできない場合やマウントできない場合、データベースが損傷した場合等にオラクルデータベースファイル(~.dbf)を直接読み込むことによって、ファイルから有効なデータを抽出するツールです。

Oracleデータベース救済-リカバリ-運用とメンテナンス-オプティマイザサビースは詩檀ソフトに訪ねてください。

にいる方は:+86  13764045638

 

独立したcプログラム

DULは独立したCプログラムで、データファイルのテーブルから直にラインを読み取る。OracleのRDBMSを全然使われていない。DULはダーティリードする。すべてのトランザクションが提出されたと仮定する。メディア・リカバリが完成されたかを確認する必要はない。

 

最後の手段

 

 

DULはほかの方法で検索できないデータを検索できるので、これがEXP,SQL *などの代用品ではなくて、最後の手段だ。正常な環境にはふさわしくない。

DULを使う前に、RDBMSにいろんな隠しの手段が壊滅したデータベースを起動できることを知ることが必要である。記録なしのinit.oraパラメータとトランザクションがロールフォワードがスキップできて、ローるバックや特定したSMON動作が使えない。

 

 

データベースが壊滅したデータブロックがまだ大丈夫

データベースが壊滅したことはまだ大丈夫だが、独立したデータブロックが100%に正確ということを確保しないといけない。すべてをエクスポートしてテストする時に、ブロックが壊れていないことと正確なセグメントに属していることを確保してください。もし、スキャンしている時に壊れたブロックを見つけたとしたら、エラ情報がロードプログラムに印刷してエクスポートする。そして次の行かブロックをインポートする。

cluster/テーブル/インデックスのライン

DULはcluster/テーブル/インデックスのラインにあるデータをエクスポートするしかできない。これはトリガをダンプしない、ストアドプロシージャ、テーブルまたビューのSQLスクリプトを作成しません。(これを説明するデータディクショナリーはエクスポートできる)。そのデータはSQL * LoaderあるいはIMPに適応したフォーマットにエクスポートされる。同時に、SQL * Loaderマッチ制御ファイルも作成される。

DULはインデックスとインデックス組織テーブルをエクスポートできる。これはテーブルになくした行と識別子の数を確かめたい時に使える。

 

クロスプラットフォームエクスポート

クロスプラットフォームエクスポートを支持している。データベースがDUL-ホストと異なったオペレーションシステムからコピーできる。(今まで関わったデータベース/システム:Sequent/ptx, Vax Vms, Alpha Vms, MVS, HP9000/8xx, IBM AIX, SCO Unix, Alpha OSF/1, Intel Windows NT)。

強力な機能

DULの運用あるいはハングにはデータベースがどれほど壊れていることにかかわらず、ダンプできない。ほぼすべてのOracle機能を支持している。ほかの支持するデータベース構造:ラインリンク、ライン移行、ハッシュ/索引クラスタ、long型、のRAW、行ID、日付、数値、複数の空きリスト・グループ(複数の空きリスト・グループ)、ハイレベルセグメント(セグメントハイウォーターマーク)、NULLが、NULLの列が尾を表示、無制限の拡張、Oracle8の新しいデータブロックレイアウト、パーティションテーブル。後で追加したlobs、圧縮インデックス、9iR2圧縮テーブルも支持している。変数配列(VARRAY)と抽象データ型ADT(ユーザーが定義したもの)は一部だけで支持される。データはexpコマンドキットでエクスポートされたダンプファイルからリカバリできる。Unpumpについて、pumpファイルを支持するために、一部の初期的な手配を完成した。

 

支持するRDBMSバーション

DULはOracle 6以後のバーションに適応する。DULはすでに6.0.26から10.2までのバーションテストを経過し、古いデータブロックヘッダー配置(6.0.27.2前)も支持する。

マルチバイト支持

DUL可转换为UTF8。这是为了存储在UTF16的 NCLOBS。

DULはシングルバイトのアプリケーションである。そのコマンドパーサはマルチバイト文字を理解できないが、あらゆるマルチバイトをエクスポートできる。すべてのトラブルに対して、解決策がある。

注意

MLSLABELS

信頼されたがOracleマルチレベルのセキュリティステッカー

LONGRAW

DULは(long)rawsをエクスポートできる。SQL * Loaderですべてのlong rawsがふさわしいフォーマットで格納されるので、long rawsとblobsがこの二つのモードでエクスポートされる。

Oracle8オブジェクトオプションとLOBS

まだネストされたテーブルを支持していないが、必要としたら、我社に連絡してください。Varray、ADT及びコアとして格納されるlobを支持する。SQL * LoaderモードとEXPモードでCLOBSもNCLOBSも支持される。EXPモードの場合に、BLOBSを処分してください。SQL * Loaderモードで作成された16進法フォーマットが今正確にロードしていない。

ポータビリティ

ANSI-C コンパイラを通って、DULをどんなオペレーションシステムにも移植できる。DULは既にいろんなUNIX,VMSとWindowsNTに移植した。いま、あらゆるの構造はgccとLinuxのクロスコンパイラ環境で完成する。

RDBMS 内部知識

Oracle RDBMSの内部的知識をよく把握すればDULをよりうまく使える。

DULのセットアップと使用

セットアップファイル

DULは二つのセットアップファイルがあるので、“init.dul”にすべてのの設定パラメータ含んでいる。(キャッシュサイズ、ヘッダのレイアウト、Oracleデータ・ブロック・サイズ、出力ファイルフォーマット)コントロールファイルで“control.dul”、データベースのデータファイル名とASMディスクをしていできる。

データファイルディクショナリーが使える

SYSTEMテーブルスペースのデータファイルが使えるなら、Oracleデータディクショナリーが使える。Oracleがこれらファイルに手配した数字と名前は“control.dul”ファイルに追加してください。また、ファイルの数とほかのテーブルスペースも追加する必要がある。これらのテーブルスペースがは最終的にはテーブルとデータをエクスポートする必要がある。これらのファイルを追加しないと、データディクショナリーのエクスポートステップに支障がでないが、後のテーブルのエクスポートが問題になる。

USER$, OBJ$, TAB$ and COL$がエクスポートできる場合に、DULを使ってください

ステップは以下の通り:

  • ターゲットデータベースにDULを配置する。つまり、正確なdulとdulを立ち上げる必要がある。SYSTEMテーブルスペースのデータファイルの数はすべてのテーブルとデータのデータファイルと一緒にcontrol.dulに追加してください。Oracle8以後のバーションで、テーブルスペースの数と関連するファイルの数はすべてのデータファイルで指定する必要がある。
  • ”BOOTSTRAP;”コマンドを使ってエクスポートする。起動処理中には互換性のセグメントがみつけて、bootstrap$をエクスポートする。古い“dul dictv7.ddl”がいらない。
  • データファイルをエクスポートして、以下のコマンドを使ってください:
    • “UNLOAD TABLE [ owner>.]table ;(;を忘れないでください)
      • データ定義やテーブルのデータをエクスポートする
    • “UNLOAD USER user name ;
      • 指定したユーザーにすべてのテーブルとデータをエクスポートする
    • “UNLOAD DATABASE ;

これですべての使用可能なデータベーステーブルをエクスポートできた。

 

 

使用可能なデータディクショナリーがない場合

もしSYSTEMテーブルスペースのデータファイルが使えなければ、unloadでデータをエクスポートできるが、USER,TABLEおよびCOLUMの名前を知らない。テーブルを認定する作業が大変になるが、まったく完成できないわけがない。アプリケーションとアプリケーションテーブルをより深く理解する必要がある。列タイプはDULによって当てられるが、テーブルと列の名前をなくした。DULが使用している多くの情報が変わらない。

DULを使っているのに、SYSTEMテーブルスペースを使わない

步骤如下:

ステップは以下の通り:

  • ターゲットデータベースにDULを配置して、正確なdulとdulを作成する。この場合に、control.dulファイルがエクスポートされたテーブル、データの数およびデータファイルの名前が必要としているが、SYSTEMテーブルスペースが必要としていない
  • SCAN DATABASE;:データベースをスキャンして、セグメンテーションマップを作成する。
  •  SCAN TABLES; or SCAN EXTENTS; 統計行を収集する。
  • ステップ3のインポートでなくしたテーブルを見つけ出す。
  • 見つけ出したテーブルをエクスポートする。

自動検索

より容易くなくしたテーブルを見つけ出すために、seen_tab.datとseen_col.datの統計情報が新たなデータベースにロードする。テーブルを再構造したい場合に、二つのSQL * Plusスクリプト(fill.sqlとgetlost.sql)を通って、なくしたテーブルの構造情報が「可視」テーブルにスキャンされた情報とマッチする。

ヒントとトラップ

 

  • 名前はDULと関連していない、データをロードする必要がある人だけと関連している。けど、エクスポートされたデータがどこのテーブルに属しているかを知らないと、データがなんの価値もない。
  • 推測列が間違っている可能性があります。不明である場合にあっても保守的なアルゴリズムが決定します。
  • 表示後方列はNULLデータベースに格納されていません。最後の列はNULL値のみが含まれている場合ので、そのスキャンは検出されません。 (テールが正しく処理された輸出表示にNULLカラム)。
  • テーブルが削除されると、説明のみのデータ辞書から除去されます。データ・ブロックが新しい段落に再利用している場合を除き、それ以外の場合は上書きされません。スキャンソフトウェアは、削除されたテーブルを参照することができます。
  • 表の行は無視されません。新しいオブジェクトIDが古いオブジェクトよりも高いです。テーブルが再構築される場合、同じテーブルの試験および生産のバージョンがある場合、または、識別オブジェクトを決定するために用いることができます。

 

DDLDULディスクドライブ言語)エクスポート声明概要

 

DULはSQLのようなコマンドインタフェースを使っている。エクスポートしたセグメント、テーブル、ユーザー及びすべてのデータベース全体のDDL文。必要としているデータディクショナリー情報がDDL文で前にエクスポートされたデータディクショナリー。以下の三つの文はDEPTテーブルをエクスポートする。データディクショナリーとセグメントマップが使用可能であれば、一番よく見られる形式は:

UNLOAD TABLE scott.dept;

すべての関連情報も文に指定できる:

REM Columns with type in the correct order

REM The segment header loaction in the storage clause

UNLOAD TABLE dept( deptno NUMBER, dname CHAR, loc CHAR)               STORAGE( EXTENTS ( FILE 1 BLOCK 1205 ));

 

Oracleバーション6:

REM version 6 data blocks have segment header location in each block        ALTER SESSION SET USE_SCANNED_EXTENT_MAP = TRUE;        UNLOAD TABLE dept( deptno NUMBER, dname CHAR, loc CHAR)               STORAGE( EXTENTS ( FILE 1 BLOCK 1205 ));

Oracle 7:

Oracle7:

REM Oracle7 data blocks have object id in each block

ALTER SESSION SET USE_SCANNED_EXTENT_MAP = TRUE;        UNLOAD TABLE dept( deptno NUMBER, dname CHAR, loc CHAR)               STORAGE( OBJNO 1501 );

 

DULインポートフォーマット

無傷な行しかエクスポートファイルに書入れない。これに対して、各行は、キャッシュされているから。Bufferの大きさはinit.dulのバラメタBUFFERで変更できる。高いBUFFERバラメタが速いスピードに等しくない、それは完全な行を保持するのに十分な大きさでなければなりません。

有三种不同的输出格式模式

三つのインポートフォーマットパタンがある:

  • インポートパタン
  • SQL * Loaderパタン:フーロデータファイル
  • SQL * Loaderパタン:固定した物理記録データファイル

 

エクスポートモード

作成したファイルはEXPによって作成したファイルのエクスポートと全然違う!そのファイルはIMPでロードできる一番小さいフォーマットである。’テーブルごとに独立したIMPファイルが作成される。これは単純なダンプファイルである。ヘッダ、insert table文とテーブルデータ、一番小さいなcreate table文を含んでいるが、ストレージ句、またはトリガーを含んでいない。(列タイプとstorage文がない)。作成されたヘッダでファイルの文字セットの表示はV6タイプである。それはASCIIの文字セットに基づいている。エクスポートを使いたいなら、init.dulバラメタEXPORT_MODEをTRUEに設定してください。

作成された偽ダンプファイルは文字セット情報セットNLS_LANGを含んでいないから、元のデータベースにマッチできない。エクスポートモードで、文字セットが変更されない。

 

SQL * Loaderモード

データはこのモードで二つの状況が分けられる:1.パタンが全然変更できない。2.パタンが全部UTF8に変更する。その前提はLDR_OUTPUT_IN_UTF8を設定した。データファイルが独立した文字が必要としているから、混合文字セット環境でこの設定が必要としている。

データをロードしている時に、必要ではないデータ文字セットの変更を避けるために、NLS_LANGを設定して元のデータベースにマッチする必要があるかもしれない。

最近二つのSQL * Loaderインポートフォーマットモードで、列はスペースで区切り、二重引用符で囲まれている。データでの二重引用符は倍になる。SQL * Loaderはその点を意識し、一つしかロードしない。init.dulバラメタLDR_ENCLOSE_CHARで二重引用符でかこまれた文字を思うままに変更する。

データストリーミングモード

このモードでは特別なところがない。記録の後には行チェンジコードが印刷される。これはコンパクトモードで、データに行チェンジコードが含んでいない場合に適用する。 データストリーミングモードを起動したいなら、LDR_PHYS_REC_SIZE = 0を設定してください。

init.dul

 

固定物理レコード

データに行チェンジレコードが含んでいるであれば、このモードは必ず必要としている。論理レコードと完全なラインはいくつかの物理記録によって構成されている。デフォルトの記録の長さは81で、VT220に適用する。物理記録の大きさはinit.dulのLDR_PHYS_REC_SIZEで指定できる。

インポートファイル名

作成されたデータファイルの名前はowner name_table name.ext。IMPロード可能な拡張子は“.dmp”である。“.dat”と“.ctl”は変数が代わられることとほかのトラブルを避けるためのSQL * Loaderのデータファイルとコントロールファイルである。(アルファベット、数字及び’_’が使用できる)。

FILEバラメタを設定したとしたら、作成された名前がFILEnnn.extになる。ファイルシステムが長すぎる名前を支持していない場合にこの方法で対応できる。

 

DUL INTERNALS

必要な情報

 

データベースブロックからテーブルデータをエクスポートしたい場合に、以下の情報が必要としている。

  1. 列//clusterクラスタ情報:列の数とタイプ。CHARまたVARCHAR列の最大の長さ。グルプ列及びグルプの中のテーブルの数。この情報はunloadで得られる。あるいは先にエクスポートされたUSER $,OBJ $,TAB $及びCOL $で獲得する。
  2. セグメント/セクタ情報:テーブルをエクスポートするときに、データセグメントヘッダでのextentテーブルがあらゆるデータブロックの位置を確かめるときに使われる。このデータセグメント(ファイルとブロックの番号)の位置はunload文で指定する。もしセグメントヘッダが正確じゃない/使えない場合に、もう一つ方法がある。DULがデータベースごとにスキャンし、自身のセクタマップを作成できる。

バイナリヘッダ

セグメントヘッダのC-Structsはそのままコピできない。ある特別な機能によって検索される。構造メンバーのすべての代償がDULに組み込まれる。この方法で、クロスプラットフォームエクスポートすることができるようになる。(HPでMVSが作成したデータファイルをエクスポートする)バイト順序の除いて以下四つの配置タイプが発見された。

  1. VAX VMSとNetware:構造メンバーの間で揃えないままで埋める。
  2. 韓国Ticom Unixマシン:構造メンバー16進数揃え
  3. MS / DOS :16進数揃えと16数字長さ。
  4. そのほか(Alpha VMSも含む):構造メンバーとメンバーの大きさに揃える。

 

マシン依存

マシンは以下の通りバラメタで配置する:

word(ビッグ/リトルエンディアン)バイトオーダー

DBA(ブロックアドレス)FILE#でより低い部分の数

C-Structでのメンバー揃え

Oracleファイルヘッダブロックあるいはバイトのかず

セグメントヘッダ構造で使用している文の大きさ

データディクショナリーをエクスポート

もしデータディクショナリーのファイルがまだ壊れたいないとすれば、DULがデータベースのデータディクショナリーをエクスポートできる。使いたいデータディクショナリーに対して、内部的なテーブルがまず外部ファイルへエクスポートする必要がある:(USER $,OBJ $,TAB $和COL $)。

Bootstrap命令で必要とするテーブルを見つけてエクスポートする・

DDL(DULディスクライブ言語)ルール

DDL(DUL描述语言)规范

[ ALTER SESSION ] SET init.dul parameter =  value ;

Most parameters can be changed on the fly.

 

BOOTSTRAP [LOCATE | GENERATE | COMPLETE

| UNLOAD   Bootstrap$ segment header block address ];

Bootstraps the data dictionary. Default is COMPLETE.

LOCATE finds and unloads the bootstrap$ table.

GENERATE builds a ddl file based on inforation in the cache.

COMPLETE is in fact LOCATE, followed by GENERATE (two times)

 

COMMIT;

Writes the changed block to the data file.

 

CREATE BLOCK INDEX  index_name  ON  device ;

 

 

 

ブロックインディクスは壊れたファイルシステムで見つけた有効なOracleブロックのアドレスを含んでいる、これは多数のディスクイメージを合併するとき、そして壊れたファイルシステムからエクスポートするときに使われる。これは極端なファイルシステムトラブルの場合に限って使える。

DESCRIBE  owner_name  . table_name ;

 

DUMP [ TABLESPACE  tablespace_no ]

[ FILE  file_no  ]

[ BLOCK  block_no  ]

[ LEVEL  level_no  ] ;

Not a complete blockdump, mainly used for debugging.

The block address is remembered.

 

EXTRACT  asm file name  to  output file name  ;

Copies any ASM file from a disk group to the file system.

(there was a problem with online redologs this needs more testing)

 

MERGE block_index INTO [  segment  ];

 

 

 

合併コマンドはインディクスファイルの情報を使って、ファイルの数と目標idの組合の中で可能なデータブロックを確認できる。そして候補ブロックをデータファイルのブロックと比べる。もし今のブロックが壊れていた場合あるいはもっと古いscnが存在するの場合候補ブロックがデータファイルに書き込まれる。これは極端トラブルのときに使える。

 

REM any_text_you_like_till_End_Of_Line : comment

REM  NOT allowed inside ddl statements. ( To avoid a two layer lexical scan).

 

ROLLBACK; # Cancels the UPDATE statements.

 

SHOW     DBA  dba ;                # dba -> file_no block_no calculator

| DBA  rfile_no block_no ;  # file_no block_no -> dba calculator

| SIZES ;                   # show some size of important structs

| PARAMETER;                # shows the values of all parameters

| LOBINFO;                  # lob indexes found with SCAN DATABASE

| DATAFILES;                # summary of configured datafiles

| ASM DISKS;                # summary of configured asm disks

| ASM FILES;                # summary of configured datafiles on asm

| ASM FILE  cid      # extent information for asm file

 

UNEXP [TABLE] [  owner  . ]  table name

(  column list  ) [ DIRECT ]

DUMP FILE  dump file name

FROM  begin offset  [ UNTIL  end offset  ]

[ MINIMUM  minimal number of columns  COLUMNS ] ;

 

To unload data from a corrupted exp dump file. No special setup

or configuration is required, just the compatible parameter.

The start offset should be where a row actually begins.

 

UNPUMP

To unload data from a corrupted expdp (datapump) dump file.

This is still work in progress, the basic commands work

but rather complex to use. Contact me if this is needed.

 

UNLOAD DATABASE;

 

UNLOAD USER user_name;

 

UNLOAD [TABLE]  [  schema_name . ]  table_name

[ PARTITION(  partition_name ) ]

[ SUBPARTITION(  sub_partition_name ) ]

[ (  column_definitions ) ]

[  cluster_clause  ]

[  storage_clause  ] ;

 

UNLOAD EXTENT  table_name

[ (  column_definitions  ) ]

[ TABLESPACE  tablespace_no  ]

FILE  extent_start_file_number

BLOCK extent_start_block_number

BLOCKS  extent_size_in oracle_blocks ;

 

UNLOAD LOB SEGMENT FOR [  schema_name . ]  table_name   [ (  column name  ) ] ;

 

UNLOAD LOB SEGMENT STORAGE ( SEGOBJNO data obj#) ;

 

UPDATE [ block_address ] SET UB1|UB2|UB4 @ offset_in_block = new_value ;

UPDATE [ block_address ] SET  block element name  = new_value ;

Now and then we can repair something.

Patches the current block and dumps it.

You can issue multiple UPDATE commands.

Block is not written yet, use COMMIT to write.

 

storage_clause ::=

STORAGE ( storage_specification  [ more_storage_specs ] )

 

storage_specification ::=

OBJNO object_id_number

|       TABNO cluster_table_number

|       SEGOBJNO cluster/data_object_number       /* v7/v8 style data block id */

|       FILE  data_segment_header_file_number     /* v6 style data block id */

BLOCK data_segment_header_block_number )

|       any_normal_storage_specification_but_silently_ignored

 

SCAN DATABASE;

 

 

あらゆるデータファイルのブロックをスキャンして、いくつのファイルを作成する。

セグメントヘッダ(インディクス/グルプ/テーブル)のdat情報を見つけ出す:(目標ID、ファイル番号及びブロック番号)。

連続なテーブル/グルプのデータブロックのdat情報。このファイル(選択可能、init.dul:SCAN_DATABASE_SCANS_LOB_SEGMENTS= TRUE)に限る)。の可能性が大きいである。同時に、必要なメモリーの大きさが問題になるかもしれない。目的は二つがある:1.テーブルをエクスポートするときに、壊れがちなlobインディクスをリカバリする。2. Lobセグメントをエクスポートする(既に削除されたlobまたlobインディクスとlobセグメントがない)

SCANNEDLOBPAGE.datの意味:(segobj#,lobid,fat_page_no,version( wrap, base),ts#,file#,block#)

 

DDLDULディスクライブ言語)サマリー

UNLOAD EXTENTUNLOAD TABLEルール:

extent mapエクステントマップ

 

 

UNLOAD TABLEはextent mapエクステントマップが必要とする。99.99%の場合に、セグメントヘッダのエクステントマップが使える。極めてまれにセグメントがなくした場合に、データベースをスキャンし、ゾーンマップを作成できる。

すべてのデータブロックがそれぞれのセグメントIDを持っている。だが、V6とV7の間に根本的な違いがある。Oracle6によって作られたセグメントブロックがセグメントブロックのアドレスがある。Oracle7によって作られたデータブロックはヘッダにセグメントIDを持っている。

 

列の定義

列の定義はセグメントに格納する順番を指定する必要がある。col$.segcol#で指定できる。CREATE TABLE言語で指定した列の順番と同じのようにする必要がない。グルプの列を前に移し、longを後ろに移る。ALTER TABLEコマンドでテーブルに追加する列はいつも最後で格納する。

 

 

 

一つのセグメントをエクスポートする

UNLOAD EXTENTは隣接するブロックをエクスポートするときに使える。エクスポートするセグメントはSTROEAGE文で指定する必要がある。一つのセグメントを指定する場合にSTORAGEを使ってください。(EXTENTS(FILE fno BLOCK bno BLOCKS #blocks))(FILEとBLOCKが指定した第一のブロック、BLOCKSセグメントの大きさ。

 

DUL具体的な列タイプ

二つ例外なDULデータタイプがある:

IGNORE:この列は存在していないようにスキップされる

UNKNOWN:列ごとにヒューリスティック推測がある

SQL * Loaderモードでもっと多くなDULデータタイプがある:

HEXRAW:列は16進数ダンプ。

LOBINFO:LOBアドレスの情報。

BINARY NUMBER:LOBインディクスで使っているマシンワード。

 

USER $OBJ $$ TABCOL $識別する

DULはRDBMSと同じなbootstrapプログラムを使っている。つまり、これはシステムデータファイルヘッダのroot dbでbootstrap$の位置を確かめる。バーションの違いによって、root dbaはbootstrap$アドレスの互換セグメント位置も含んでいるかもしれない、あるいは新たなバーションではbootstrap$テーブル自身のアドレスである。bootstrap$テーブルがエクスポートされて、その内容は前の四つのテーブル(USER $,OBJ $,$ TAB和COL $)を検索して分析する。ほかのテーブルは前の四つのテーブルの情報に基づいてエクスポートされた。

 

SCANスキャンコマンドサマリー

SCAN TABLESとSCAN EXTENTSは同じ情報をスキャンして、似たようなインポートを作成する。すべての行と列も検索されて、以下のデータを収集する:

  • 行はデータブロックで現れる時間間隔。
  • 最大の内部列の長さ
  • 列がNULLになった経過時間。
  • せめて75%印刷可能なASCIIによって組み込むようになった経過時間。
  • 100%印刷可能なASCIIによって組み込むようになった経過時間。
  • 列が有効なOracle数字になった経過時間。
  • 列が悪くない数字になった経過時間(ゼロで始まることも終わることもない)
  • 列が有効な日付きになった経過時間。
  • 列は有効なrowidになった経過時間。

これらの統計は組み込まれ、一種の列タイプとして提出される。このアドバイスを採用し、結果をエクスポートする。これらの統計データは二つのファイル(seen_tab.datとseen_col.dat)にダンプする。SQL * LoaderとSQL * Plusスクリプトがあれば、一部の識別プロセスが自動的に完成する。(getlostと呼ばれている)。

 

デスクライブdescribe

このようなデスクライブコマンドがあって、DULディクショナリーメモリーで使用できて、テーブルのディクショナリー情報を示す。

DUL起動手順:

起動プロセスは以下のようなスキップが必要である:

  • バラメタファイル“dul”が処理された
  • DULコントロールファイル(ディフォルトは“dul”)がスキャンされた。
  • USER$,OBJ$,TAB $およびCOL $のダンプをロードしてみてください。もし存在すれば、DULのデータディクショナリーメモリーに格納してください。
  • Datとdatをロードしてみてください
  • DDL文を受け入れ、または初めのバラメタになったDDLスクリプトを実行してください。

 

init.dulで指定できるDULバラメタ

ALLOW_TRAILER_MISMATCH

BOOLEAN

この機能を使わないでください。より多くの行を作成されないので、完全にその構造を理解し、なぜ自分がこの機能を使いたくなったかを十分理解したうえで使える。この機能は正確なブロックtrailerテストをスキップした。このテストで失敗したブロックは壊滅した欠片なので、ブロックを修復する迷惑を省みた。

 

もしディクショナリーはデータファイルより古い場合に、データ目標IDはtruncateされたテーブルと違っている。このバラメタをtrueにしてください、アラームを発生するが、セグメントヘッダの値を使っているから、まだ大丈夫。すべてのブロックも全面的にテストされる。

 

ASCII2EBCDIC

BOOLEAN

(var)charフィールドはEBCDICからASCIIに書き変わる必要がある。(ASCIIホストでMVSデータベースをエクスポートするときに使う)

 

BUFFER

NUMBER(バイト)

エクスポートとSQL * Loaderモードで使っているライン出力バッファ(buffer)の大きさはまずそのバッファに格納されて。違っていない行はそのままインポートファイルに書き込む。

 

COMPATIBLE

NUMBER

データベースバーション:有効値は6.7.8.9。バラメタを指定する必要がある。

 

CONTROL_FILE

TEXT

DULコントロールファイル名前(ディフォルト:“ control.dul”)

DB_BLOCK_SIZE

NUMBER

バイトで示したOracleブロックの大きさ(最大32K)

 

DC_COLUMNS

NUMBER

DC_OBJECTS

NUMBER

DC_TABLES

NUMBER

DC_USERS

NUMBER

Dulディクショナリーメモリー大きさ。もし一つが低すぎるとしたら、自動的に大きさを調整する。

 

EXPORT_MODE

BOOLEAN

エクスポートモードまたは SQL*Loaderモードを使ってください

 

FILE

TEXT

(ダンプあるいはデータ)ファイル名を作成する基礎である。 8.3 DOSのようなファイルシステムに適応する。

 

FILE_SIZE_IN_MB

NUMBER (Megabytes)

最大のダンプファイル大きさ。ダンプファイルはいくつかの部分に分割する。ファイルごとに一つのヘッダを持っていて、独立でロードできる。

 

LDR_ENCLOSE_CHAR

TEXT

The character to enclose fields in SQL*Loader mode.

LDR_PHYS_REC_SIZE

NUMBER

作成したloaderデータファイルの物理記録の大きさ

 

LDR_PHYS_REC_SIZE = 0固定した記録がない。すべての記録は改行記号で終わる。

LDR_PHYS_REC_SIZE > 2: 固定した記録の大きさ

MAX_OPEN_FILES

オペレーションシステムレベルでオープンなデータファイルを最大にしてください。

 

OSD_BIG_ENDIAN_FLAG

マシン言語で表示したバイト手順。Big EndianもMSBと呼ばれている。DULは運用している機械でディフォルトを設定できる。

 

OSD_DBA_FILE_BITS

OSD_FILE_LEADER_SIZE

bytes/blocks added before the real oracle file header block

OSD_C_STRUCT_ALIGNMENT

C構造メンバー揃え(0,16あるいは23)。ディフォルトの32は大多数のポートに対しても正しい。

OSD_WORD_SIZE

MS/DOS(16)を除いて、一つのマシンワードの大きさはいつも32。

PARSE_HEX_ESCAPES

Boolean ディフォルト FALSE

解析の時に、文字列で\\xhh 16進数エスケープシーケンス。trueに設定したら、おかしい文字はエスケープシーケンスで指定できる。マルチバイト文字を指定するときにも運用できる。

USE_SCANNED_EXTENT_MAP

BOOLEAN

テーブルをエクスポートするときに、ext.datでスキャンしたゾーンマップを使っている。通常のアルゴリズムはセグメントヘッダでゾーンマップを使っているが、一部のセグメントヘッダがなくした場合にこのバラメタが使える。

WARN_RECREATE_FILES

BOOLEAN (TRUE)

既存のファイルが上書きされたとすれば、FALSEに設定してアラーム通信をキャンセルできる。

WRITABLE_DATAFILES

BOOLEAN (FALSE)

一般的に、DULはデータベースファイルだけを読み取る。けど、UPDATEと SCAN RAW DEVICEも書き出される。バラメタは予想していない損害を防げる。

例 init.dul :

# sample init.dul configuration parameters

# these must be big enough for the database in question

# the cache must hold all entries from the dollar tables.

dc_columns = 200000

dc_tables = 10000

dc_objects = 10000

dc_users = 40

 

# OS specific parameters

osd_big_endian_flag = false

osd_dba_file_bits = 10

osd_c_struct_alignment = 32

osd_file_leader_size = 1

 

# database parameters

db_block_size = 8k

 

# loader format definitions

LDR_ENCLOSE_CHAR = ”

LDR_PHYS_REC_SIZE = 81

配置ポートについてのバラメタ

RDBMS 10Gから、osdが配置しやすくなった。一般的に、すべてのバラメタがディフォルト値を使える。唯一の注意をかける必要があるのはosd_big_endian_flag、元のデータベースプラットフォームと今のマシンと異なって、クロスプラットフォームエクスポートするときに、osd_big_endian_flagの設定が正しくなければ

既に知っていったバラメタ

10GデータベースはOSDウィキリストがない場合に私たちに知らせてください。

osd_big_endian_flag

big endian あるいはlittle endian(マシンが示したバイト手順):HP,SUNbig endian:OSD_BIG_ENDIAN_FLAG = TRUE。 DEC和Intel平台是little endian :OSD_BIG_ENDIAN_FLAG = FALSE。ディフォルト値はDULが運用しているプラットフォームに対して、正しかった。

 

この点については、決まりのコツがない。以下の方法はUNIXシステムでは可能かもしれない。

echo dul | od -x

If the output is like:

0000000 6475 6c0a

0000004

You are on a big endian machine (OSD_BIG_ENDIAN_FLAG=TRUE).

 

If you see:

0000000 7564 0a6c

0000004

This is a little endian machine (OSD_BIG_ENDIAN_FLAG=FALSE).

osd_dba_file_bits

以下のコマンドを実行してください。

SQL> select dump(chartorowid(‘0.0.1′)) from dual;

 

Typ=69 Len=6: 8,0,0,0,0,0    ->       osd_dba_file_bits =  5 (SCO)

Typ=69 Len=6: 4,0,0,0,0,0    ->       osd_dba_file_bits =  6 (Sequent , HP)

Typ=69 Len=6: 1,0,0,0,0,0    ->       osd_dba_file_bits =  8 (NCR,AIX)

Typ=69 Len=6: 0,16,0,0,0,0   ->       osd_dba_file_bits = 12 (MVS)

Typ=69 Len=10: 0,0,0,0,0,64,0,0,0,0      osd_dba_file_bits = 10 (Oracle8)

OSD_C_STRUCT_ALIGNMENT

データファイルヘッダの構造配置。0:c-構造(VAX/ VMS)メンバーの間で、埋め込まれていない。16:一部の韓国ticomマシンとMS/ DOS32:構造メンバーはメンバーの大きさで配列する。

SELECT * FROM v$type_size

WHERE type IN ( ‘KCBH’, ‘KTNO’, ‘KCBH’, ‘KTBBH’, ‘KTBIT’, ‘KDBH’

, ‘KTECT’, ‘KTETB’, ‘KTSHC’) ;

一般的にosd_c_struct_alignment=32と以下のようなものがでる:

K        KTNO     TABLE NUMBER IN CLUSTER                   1

KCB      KCBH     BLOCK COMMON HEADER                      20

KTB      KTBIT    TRANSACTION VARIABLE HEADER              24

KTB      KTBBH    TRANSACTION FIXED HEADER                 48

KDB      KDBH     DATA HEADER                              14

KTE      KTECT    EXTENT CONTROL                           44

KTE      KTETB    EXTENT TABLE                              8

KTS      KTSHC    SEGMENT HEADER                            8

 

8 rows selected.

VAX/ VMSとNetwareだけに対して、osd_c_struct_alignment=0と以下のようなものがでる:

COMPONEN TYPE     DESCRIPTION                      SIZE

——– ——– ——————————– ———-

K        KTNO     TABLE NUMBER IN CLUSTER                   1

KCB      KCBH     BLOCK COMMON HEADER                      20

KTB      KTBIT    TRANSACTION VARIABLE HEADER              23

KTB      KTBBH    TRANSACTION FIXED HEADER                 42

KDB      KDBH     DATA HEADER                              14

KTE      KTECT    EXTENT CONTROL                           39

KTE      KTETB    EXTENT TABLE                              8

KTS      KTSHC    SEGMENT HEADER                            7

 

8 rows selected.

もし、異なったリストがあるとすれば、一部のハッキングと盗聴が必要とする。DULに重大な影響を与えるかもしれない。(メールBernard.van.Duijnen@oracle.com

osd_file_leader_size

 

Oracleファイルヘッダのまえのブロック/バイトの数。Unixデータファイルがエクストラ先頭ブロックが100を超えた場合にバイトオフセットと見なし、超えていなければOracleブロックの番号と見なす。

Unix    :       osd_file_leader_size = 1

Vms     :       osd_file_leader_size = 0

Desktop :       osd_file_leader_size = 1 (or 512 for old personal oracle)

Others  :       Unknown ( Use Andre Bakker’s famous PATCH utility to find out)

An Oracle7 file header block starts with the pattern 0X0B010000.

選択可能な第三フィールドのcontrol.dulでエクストラなバイトオフセットを追加できる。(AIXあるいはDEC UNIX)

コントロールファイル文法のルール:

コントロールファイル(ディフォルト名“control.dul”)はASMディスク、ブロックインディクス及びデータファイル名を指定するときに使える。

control_file_line ::= asm_disk_spec | file_piece_spec | block_index_spec

互換性は10か以上である場合に、ASMディスクも指定できる。一般的に指定したマシンの名は足りる。

DISK  device name [  disk group options  ]

 

disk group option  ::= GROUP  disk group name

| DISK_NO  disk number in group

| F1B1  File1 Block1 location

ブロックインディクスは壊滅したファイルシステムでOracleブロックにアクセスする方法の一つで、一般的には、壊れたファイルシステムが完全に削除されていないかぎり、ブランクではない。Oracleブロックの特別な配置によって、it is possible to datablocks an store their location in the block index。create block indexコマンドを参考してください。block_index_nameは普通な識別子で、唯一なファイル名を作成するときに使われる。

BLOCK INDEX  block_index_name

各エントリはデータファイルの一部を指定できる。最小の単位は一つのデータブロックである。この場合に、DULが大き過ぎるファイルに対して、いくつか2GBに過ぎない部分に割り当てられる。

普通の場合に、ファイル名を指定すればいいと思う。一つのブロックに対して、compatibleが10に超えた場合に、ファイルヘッダからファイル番号とテーブルスペース番号を読み取る。

指定したディテールとファイルヘッダと相違がでた場合、壊れたファイルヘッダからファイルをエクスポートするために、DULがアラームを発信する。チューニングするときに、ファイルヘッダをダンプできる。

選択可能な追加のシフトリーダーはエクストラなバイトオフセット、データファイルのすべてのlseek()操作に付き添った。よって、AIXもっとのマシン以外の4Kブロックをスキップできる。あるいは元のマシンでTru64d4kブロックを追加できる。

file_piece_spec ::=

[ [ tablespace_no ] relative_file_number]data_file_name

[ optional extra leader offset ]

[ startblock block_no ]

[ endblock block_no ]

例えば

# AIX version 7 example with one file on raw device

1 /usr/oracle/dbs/system.dbf

8 /dev/rdsk/data.dbf 4096

 

# Oracle8 example with a datafile split in multiple parts, each part smaller than 2GB

0  1 /fs1/oradata/PMS/system.dbf

1  2 /tmp/huge_file_part1 startblock 1 endblock 1000000

1  2 /tmp/huge_file_part2 startblock 1000001 endblock 2000000

1  2 /mnt3/huge_file_part3 startblock 2000001 endblock 2550000

 

# ASM disks for two disk groups

disk /media/maxtor/asm/dgn1

disk /media/maxtor/asm/dgn2

disk /media/maxtor/asm/dgn3

disk /media/maxtor/asm/dgn4

disk /media/maxtor/asm/dgodd

 

# system datafile in the first asm disk group

+DGN/db102/datafile/system.257.621616979

 

# users datafile in a different disk group

+DGODD/db102/datafile/users.257.621616683

 

# a so called big file tablespace, use 1024 for the file#

8 1024 /home/oracle/v102/dbs/bigfilets

 

# Or let DUL find out itself from the header

/home/oracle/v102/dbs/bigfilets

 

# one tablespace with a different block size

/home/oracle/v102/dbs/ts16k.dbf block_size 16k

 

# or let DUL find out by header inspection

/home/oracle/v102/dbs/ts16k.dbf

会話を例でエクスポートされた:DULデータディクショナリーに使える。

1.ふさわしい “init.dul”を作成する

2. control.dulを作成する。

sqlplus /nolog

connect / as sysdba

startup mount

set trimspool on pagesize 0 linesize 256 feedback off

column name format a200

spool control.dul

select ts#, rfile#, name from v$datafile;

exit

edit the result

 

For Oracle8 a different query must be used:

select ts#, rfile#, name from v$datafile;

  1. DULとbootstrapを起動する。

$ dul

 

Data UnLoader 10.2.1.16 – Oracle Internal Only – on Thu Jun 28 11:37:24 2007

with 64-bit io functions

 

Copyright (c) 1994 2007 Bernard van Duijnen All rights reserved.

 

Strictly Oracle Internal use Only

DUL> bootstrap;

Probing file = 1, block = 377

. unloading table                BOOTSTRAP$      57 rows unloaded

DUL: Warning: Dictionary cache DC_BOOTSTRAP is empty

Reading BOOTSTRAP.dat 57 entries loaded

Parsing Bootstrap$ contents

DUL: Warning: Recreating file “dict.ddl”

Generating dict.ddl for version 10

OBJ$: segobjno 18, file 1

TAB$: segobjno 2, tabno 1, file 1

COL$: segobjno 2, tabno 5, file 1

USER$: segobjno 10, tabno 1, file 1

Running generated file “@dict.ddl” to unload the dictionary tables

. unloading table                      OBJ$   52275 rows unloaded

. unloading table                      TAB$    1943 rows unloaded

. unloading table                      COL$   59310 rows unloaded

. unloading table                     USER$      70 rows unloaded

Reading USER.dat 70 entries loaded

Reading OBJ.dat

52275 entries loaded and sorted 52275 entries

Reading TAB.dat 1943 entries loaded

Reading COL.dat 59310 entries loaded and sorted 59310 entries

Reading BOOTSTRAP.dat 57 entries loaded

Some more messages for all the other TABLES

Database character set is WE8ISO8859P1

Database national character set is AL16UTF16

DUL> unload user SCOTT;

About to unload SCOTT’s tables …

. unloading table                       EMP      14 rows unloaded

会話を例でエクスポートされた:DULデータディクショナリーに使えない。

 

1.ふさわしい “init.dul”を作成する

2. control.dulを作成する。

3.データベースのセグメントヘッダとセクションをスキャンする

$ dul

UnLoader: Version 2.0.0.0 – Very Restricted on Tue May 16 11:10:16 1995

Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved.

DUL> scan database;

data file 1 20480 blocks scanned

data file 4 7680 blocks scanned

data file 5 512 blocks scanned

DUL>quit

  1. DULを再起動して見つけ出したテーブルから列の統計を獲得する、大量なインポートが作成された。

echo scan tables \; | dul > scan.out&

 

[ many lines here]

 

 

Object id 1601 table number 0

UNLOAD TABLE T1601_0 ( C1 NUMBER, C2 UNKNOWN, C3 UNKNOWN, C4 NUMBER, C5 DATE

, C6 NUMBER, C7 NUMBER, C8 NUMBER )

STORAGE ( TABNO 0 EXTENTS( FILE 1 BLOCK 10530));

 

Colno  Seen MaxIntSz Null% C75% C100 Num% NiNu% Dat% Rid%

1    14        3    0%   0%   0% 100% 100%   0%   0%

2    14        6    0% 100% 100% 100%  14%   0%  21%

3    14        9    0% 100% 100% 100%  14%   0%   0%

4    14        3    7%   0%   0% 100% 100%   0%   0%

5    14        7    0%   0%   0%   0%   0% 100%   0%

6    14        3    0%   0%   0% 100% 100%   0%   0%

7    14        2   71%   0%   0% 100% 100%   0%   0%

8    14        2    0%   0%   0% 100% 100%   0%   0%

 

“7369” “SMITH” “CLERK” “7902” “17-DEC-1980 AD 00:00:00″ “800” “” “20”

 

“7499” “-0.000025253223″ “SALESMAN” “7698” “20-FEB-1981 AD 00:00:00″ “1600” “30+

 

0″ “30”

 

“7521” “WARD” “SALESMAN” “7698” “22-FEB-1981 AD 00:00:00″ “1250” “500” “30”

 

“7566” “JONES” “MANAGER” “7839” “02-APR-1981 AD 00:00:00″ “2975” “” “20”

 

“7654” “MARTIN” “SALESMAN” “7698” “28-SEP-1981 AD 00:00:00″ “1250” “1400” “30”

 

[ many more lines here ]

ここの内容はよく見られるとおもう。これらの情報とempテーブルの理解に基づき、作成してください。

UNLOAD TABLE emp ( empno number, ename char, job char, mgr number,

hiredate date, sal number, comm number deptno number)

STORAGE ( TABNO 0 EXTENTS( FILE 1 BLOCK 10530));

1.この文でempをエクスポートする:

$ dul

UnLoader: Version 2.0.0.0 – Very Restricted on Tue May 16 11:46:33 1995

Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved.

Loaded 350 segments

Loaded 204 extents

Extent map sorted

DUL> UNLOAD TABLE emp ( empno number, ename char, job char, mgr number,

DUL 2> hiredate date, sal number, comm number deptno number)

DUL 3> STORAGE ( TABNO 0 EXTENTS( FILE 1 BLOCK 10530));

. unloading table                       EMP      14 rows unloaded

DUL>quit

 

Sessionをエクスポートする:正しくないinit.dulバラメタ

違ったosd_dba_file_bitsの大きさ

よって、以下のようなインポートが出てくる。一般的には発生しない。デモ・データベースを作成して、DUL記録の問い合わせ(HTMLページ)で検索してください。

DBAのミスマッチはファイルの部分にある。第二番の数字やブロック番号は正しい。

Data UnLoader: Release 3.2.0.1 – Internal Use Only – on Wed Sep 3 10:40:33 1997

Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved.

Session altered.

Session altered.

Session altered.

Session altered.

Session altered.

DUL: Warning: Block[1][2] DBA in block mismatch [4][2]

DUL: Warning: Bad cache layer header file#=1, block#=2

 

DUL: Warning: Block[1][3] DBA in block mismatch [4][3]

DUL: Warning: Bad cache layer header file#=1, block#=3

 

………..and etc……….

osd_file_leader_sizeが間違った。

以下のようなインポートになるかもしれないが、そのほかにも色々な可能性がある。ここで、block offは固定したので、In this case we are a fixed number of blocks off.ファイル番号は正しい、ブロック番号の差は変わらない。

Data UnLoader: Release 3.2.0.1 – Internal Use Only – on Wed Sep 3 10:44:23 1997

Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved.

Session altered.

Session altered.

Session altered.

Session altered.

Session altered.

 

DUL: Warning: Block[1][2] DBA in block mismatch [1][3]

DUL: Warning: Bad cache layer header file#=1, block#=2

 

DUL: Warning: Block[1][3] DBA in block mismatch [1][4]

DUL: Warning: Bad cache layer header file#=1, block#=3

 

………..and etc……….

osd_c_struct_alignmentが間違った。

以下のようなインポートになる:

Data UnLoader: Release 3.2.0.1 – Internal Use Only – on Wed Sep 3 10:46:10 1997

Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved.

Session altered.

Session altered.

Session altered.

Session altered.

Session altered.

. unloading table OBJ$

 

DUL: Warning: file# 0 is out of range

DUL: Warning: Cannot read data block file#=0, block# = 262145

OS error 2: No such file or directory

 

DUL: Warning: file# 0 is out of range

DUL: Warning: Cannot read data block file#=0, block# = 262146

OS error 2: No such file or directory

 

………..and etc……….

db_block_sizeが間違った。

DB_BLOCK_SIZEが小さ過ぎると、以下のようなインポートになる。正確なちは4096、2048に設定すれば、一般的には、このバラメタ値はOracleインスタンスのinit.oraファイルから得る。そして正確に設定できない。

Data UnLoader: Release 3.2.0.1 – Internal Use Only – on Thu Sep 4 12:38:25 1997

Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved.

Session altered.

Session altered.

Session altered.

Session altered.

Session altered.

DUL: Warning: Block[1][2] DBA in block mismatch [513][1159680]

DUL: Warning: File=1, block 2: illegal block version 2

DUL: Warning: Block[1][2] Illegal block type[0]

DUL: Warning: Bad cache layer header file#=1, block#=2

 

DUL: Warning: Block[1][4] DBA in block mismatch [1][2]

DUL: Warning: File[1]Block[4]INCSEQ mismatch[90268!=0]

DUL: Warning: Bad cache layer header file#=1, block#=4

 

DUL: Warning: Block[1][6] DBA in block mismatch [1][3]

DUL: Warning: File[1]Block[6]INCSEQ mismatch[139591710!=86360346]

DUL: Warning: Bad cache layer header file#=1, block#=6

 

………..and etc……….

QUOTE MISSING

以下のようなエラになったのはデータディクショナリーテーブル“USER$,OBJ$,$ TAB及びCOL$”が正確に作成されていないからである。このエラを解決するために、すべてのdictv6.ddlまたはdictv7.ddlを削除し、datと.ctlファイルを作成して再起動すればいい。

Data UnLoader: Release 3.2.0.1 – Internal Use Only – on Wed Sep 3 10:49:30 1997

 

Data UnLoader: Release 3.2.0.1 – Internal Use Only – on Wed Sep 3 10:49:30 1997

 

DUL: Error: Quote missing

壊滅したEXPダンプファイルからデータをリカバリする:UNEXP

EXPダンプファイルに対して何一つも知らないとしたら、リカバリが大変になる。以下は簡単な説明である。ファイルヘッダを除いて、ダンプファイルは部分の標識を識別できる。すべてのテーブルにはSQL文がある。一番面白い部分はcreate table文。そしてテーブル文にインサートして、情報にバインディングしてください。そして、実際の例で、列ごとに2バイト長があって、実際の列データを付いていない。より長い列にはこんなコツがある。列データの終わりで特別な長さでOXFFFFを標識する 行のヘッダには標識がない。壊れたあとの再同期はエラを試す。壊れた部分は検知できない。そのフォーマットはDIRECTエクスポートと違っている。DIRECTエクスポートに対してDIRECTオプションを使ってください。指定したオフセットは行のヘッダになる。一般的には初めてのバインディングされた       アレイから始まるが、最善な柔軟性になるために、行データのどこからでもいい。

第一歩はダンプファイルで転移したSQL文を見つけ出す。すべてのインポート行は転移した位置から始まる。

 

DUL>  scan dump file expdat.dmp;

0: CSET: 1 (US7ASCII)                # Character set info from the header

3: SEAL EXPORT:V10.02.01             # the Seal – the exp version tag

20: DBA SYSTEM                       # exp done as SYSTEM

8461: CONNECT SCOTT                  # section for user SCOTT

8475: TABLE “EMP”

# complete create table staement

8487: CREATE TABLE “EMP” (“EMPNO” NUMBER(4, 0), “ENAME” VARCHAR2(10),

“JOB” VARCHAR2(9), “MGR” NUMBER(4, 0), “HIREDATE” DATE, “SAL” NUMBER(7, 2),

“COMM” NUMBER(7, 2), “DEPTNO” NUMBER(2, 0))  PCTFREE 10 PCTUSED 40

INITRANS 1 MAXTRANS 255 STORAGE(INITIAL 65536 FREELISTS 1

FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE “USERS” LOGGING NOCOMPRESS

 

# Insert statement

8829: INSERT INTO “EMP” (“EMPNO”, “ENAME”, “JOB”, “MGR”, “HIREDATE”,

“SAL”, “COMM”, “DEPTNO”) VALUES (:1, :2, :3, :4, :5, :6, :7, :8)

 

# BIND information

8957: BIND information for 8 columns

col[  1] type 2 max length 22

col[  2] type 1 max length 10 cset 31 (WE8ISO8859P1) form 1

col[  3] type 1 max length 9 cset 31 (WE8ISO8859P1) form 1

col[  4] type 2 max length 22

col[  5] type 12 max length 7

col[  6] type 2 max length 22

col[  7] type 2 max length 22

col[  8] type 2 max length 22

Conventional export                  # Conventional means NOT DIRECT

 

9003: start of table data            # Here begins the first row

现在从create table语句和直接/常规信息和列数据的开头创建unexp语句。

これからはcreate table文からダイレクト/一般情報と列データの初めての部分でunexpを作成する。

UNEXP TABLE “EMP” (“EMPNO” NUMBER(4, 0), “ENAME” VARCHAR2(10),

“JOB” VARCHAR2(9), “MGR” NUMBER(4, 0), “HIREDATE” DATE, “SAL” NUMBER(7, 2),

“COMM” NUMBER(7, 2), “DEPTNO” NUMBER(2, 0))

dump file expdat.dmp from 9003;

 

Unloaded 14 rows, end of table marker at 9670 # so we have our famous 14 rows。

この操作によって、普通のSQL * Loaderファイルとそれにマッチするコントロールファイルを作成される。インポートファイルでエクストラな列が付き添う。APは行が部分的と意味している。(なくした一部の列)Rは最同期に意味する、これは最同期の第一行。Oは重なり、前の行にエラがある。新しい行はほかの部分に重なる。

 

 

 

 

 

目录

コラム

~~~~~~~~~~~~~~~~~

  1. サマリー
  2. DULを使う

2.1ふさわしいinit.dulファイルを作成する

2.2control.dulファイルを作成する

2.3目標情報をエクスポートする

2.4DULを使う

2.5データベースを再建する

  1. どうやってデータディクショナリーに格納された目標定義を再建できるでしょう
  2. セグメントヘッダが壊滅した時に、どうやってデータをエクスポートできるでしょう
  3. ファイルヘッダが壊滅した時に、どうやってデータをエクスポートできるでしょう
  4. システムテーブルスペースなしにどうやってデータをエクスポートできるでしょう
  5. 虫垂A:どこで実行できるファイルを見つけ出せるでしょう
  6. リファレンス
  • サマリー

この文はBernardのデータエクスポート能力に対する説明ではなく、DULをいかに活用できる方法を紹介する文である。

この文は内部的な交流に限る。どんな場合にもこの文をお客様に渡すことが許せない。DULは常に分析者に使うことあるいは分析者の監視を元に使うことを確保してください。

DUL(データエクスポート)はOracleデータベースから検知できないデータを検索できる。けどこれはSQL * Loaderの代わりではない。このデータベースは破壊されやすいから、一つ独立したデータブロックが100%に正確ということを確保してください。エクスポートするときに、ブロックが壊れていないことと正確なセグメントに属していることを確保するために、ブロックがテストされる。エラ情報がloaderに写されるが、後の行やブロックのエクスポートすることが阻止できない。

2.DULをつかう

まずデータブロックにある目標が必要とする情報を入手してください。これらの統計は、DULディクショナリーにロードされる。

この情報はデータベースが作成された時に、作成したUSER $,OBJ $,$ TAB及びCOL $表を検索して見つけ出した。DULはシステムテーブルスペースで情報を見つけ出せる。データファイルが存在しない場合に、テーブルデータファイルはコントロールファイルに含んでいる必要がある。-0urY   00000000022

2.1 ふさわしい“init.dul”ファイルを作成する

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

REMプラットフォームでバラメタを指定する

REMはよくあるプラットフォームのバラメタを獲得できる。

osd_big_endian_flag=false

osd_dba_file_bits=10

osd_c_struct_alignment=32

osd_file_leader_size=1

osd_word_size = 32222222

REM DULディクショナリーメモリーの大きさ。低すぎた場合に、起動できない。

dc_columns=2000000

dc_tables=10000

dc_objects=1000000

dc_users=400

control_file = D:\Dul\control_orcl.dul

コントロールファイルの位置と名、ディフォルトはcontrol.dul

データベースブロックの大きさ。init.oraあるいは“show parameter %db_block_size%”で見つけ出せる。

db_block_size=4096。

 

データが指定するために、エクスポート、インポートフォーマットが必要とする。

これにより、Oracleインポートツールに適用したファイルが作成されるが、作成されたファイルがEXPツールで作られたものと全然ちがう。

それはテーブル構造文とテーブルデータのテーブルダンプファイルである。

Grants、ストレージ句、トリガが含んでいない!

export_mode=true

 

REM互換バラメタは指定できて、6も7も8もいい。

compatible=8

 

そのバラメタは選択可能でREMが支持していない長すぎたファイル名(e.g. 8.3 DOS)のプラットフォームも、DUL が“owner_name.table_name.ext”を使って、ファイルフォーマットが使用出来ない場合にも指定できる。

file = dump

 

完全なリストがHTML部分でDULバラメタで獲得できる。init.dulファイルが大多数の場合にも適用できて、すべてのバラメタも含んでいて成功エクスポートすることを保障できる。

2.2“control.dul”ファイルを作成する

論理表スペースと物理データ・ファイルに対して一定な知識が必要、データベースがロードされた時に以下の問合せを実行する:

Oracle 6, 7

———–

> connect internal

> spool control.DUL

> select * from v$dbfile;

> spool off

 

Oracle 8

——–

> connect internal

> spool control.DUL

> select ts#, rfile#, name from v$datafile;

> spool off

 

必要であれば、spoolファイル、データファイルの位置とstrpe outに必要ではない情報も編集できる。

例コントロールファイルは以下の通り:

Edit the spool file and change, if needed, the datafile location and stripe

out unnecessary information like table headers, feedback line, etc…

A sample control file looks something like this :

REM Oracle7 control file

1 D:\DUL\DATAFILE\SYS1ORCL.DBF

3 D:\DUL\DATAFILE\DAT1ORCL.DBF

7 D:\DUL\DATAFILE\USR1ORCL.DBF

REM Oracle8 control file

0 1 D:\DUL\DATAFILE\SYS1ORCL.DBF

1 2 D:\DUL\DATAFILE\USR1ORCL.DBF

1 3 D:\DUL\DATAFILE\USR2ORCL.DBF

2 4 D:\DUL\DATAFILE\DAT1ORCL.DBF

 

注意:DULが大きすぎるデータファイルをスプリットするときに使える。例えば:

REM Oracle8であるデータファイルがいくつかの部分に割り当てられた。すべての部分は1GBを超えていない。

0 1 D:\DUL\DATAFILE\SYS1ORCL.DBF

1 2 D:\DUL\DATAFILE\USR1ORCL.DBF startblock 1 endblock 1000000

1 2 D:\DUL\DATAFILE\USR1ORCL.DBF startblock 1000001 endblock 2000000

1 2 D:\DUL\DATAFILE\USR1ORCL.DBF startblock 2000001 endblock 2550000

2.3 Unload the object information

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ふさわしいDDL(DUL言語)スクリプトでBULツールを起動する。データベースバーションの違いによって、三つ使用可能なスクリプトでUSER$,$ OBJ,TAB$とCOL$テーブルでエクスポートできる。

Oracle6 :> dul8.exe dictv6.ddl

Oracle7 :> dul8.exe dictv7.ddl

Oracle8 :> dul8.exe dictv8.ddl

 

Data UnLoader: Release 8.0.5.3.0 – Internal Use Only – on Tue Jun 22 22:19:

Copyright (c) 1994/1999 Bernard van Duijnen All rights reserved.

Parameter altered

Session altered.

Parameter altered

Session altered.

Parameter altered

Session altered.

Parameter altered

Session altered.

. unloading table OBJ$ 2271 rows unloaded

. unloading table TAB$ 245 rows unloaded

. unloading table COL$ 10489 rows unloaded

. unloading table USER$ 22 rows unloaded

. unloading table TABPART$ 0 rows unloaded

. unloading table IND$ 274 rows unloaded

. unloading table ICOL$ 514 rows unloaded

. unloading table LOB$ 13 rows unloaded

 

Life is DUL without it

USER$, OBJ$, TAB$ and COl$データディクショナリーのデータをSQL*Loaderファイルにエクスポートする。これはエクスポートフォーマットのダンプファイルに処理出来ない。

. unloading table OBJ$

DUL: Error: Column “DATAOBJ#” actual size(2) greater than length in column

definition(1)

………….etc……………

 

2.4 DULを使う

対話モードでDULを起動する。すべてのddlコマンドを含んでいて、データベースに必要なデータをエクスポートするスクリプトを用意してもいい。本文档で一番よく使われるコマンドを説明する。

DUL> unload database;

=> データベーステーブルごとにエクスポートする(sys’tablesも含む)

DUL> unload user ;

=>指定したユーザーが持っているすべてのテーブルをエクスポートする。

DUL> unload table ;

=>ユーザーが持っているテーブルをアンインストールする。

DUL> describe ;

=>テーブルの列及び指定したユーザーが持っているデータファイルを示す。

will represent the table columns with there relative pointers to the datafile(s) owned by the specified user.

 

DUL> scan database;

=>すべてのデータファイルのブロックをスキャンする

二つのファイルが作成される:

1.見つけ出したセグメントヘッダseg.dat情報(インディクス/グルプ/テーブル)

2.連続なテーブル/グルプのデータブロックのext.dat情報

(目標ID(V7)、ファイルとセグメントヘッダのブロック番号(V6)、ファイル番号と初めてのブロックの番号、ブロックの数、テーブルの数)

DUL> scan tables;

=> seg.datとext.datをインポートする

すべてのデータセグメントのテーブルをスキャンする。

2.5データベースを再建する

~~~~~~~~~~~~~~~~~~~~~~~~

新しいデータベースを作成する。そして、SQL * LoaderでDULが検索したデータをリカバリする。けど、テーブル構造データをエクスポートするときに、新しいデータベースにはインディクス、grants,PL / SQL及びトリガーを含んでいない。前のデータベースと完全に同じなものを手に入るため、テーブル、インディクスPL / SQLなどの作成スクリプトを再び実行してください。

3.どうやってデータディクショナリーに格納された目標定義を再建する

DULでPL / SQL(パッケージ、プロシージャ、関数、またはトリガー)、補助金、索引、制約または記憶域句(旧テーブル構造)を再建することもできるが、ちょっとだけ厄介になる。DULで関連するデータディクショナリーテーブルをエクスポートして、これらのテーブルを健全なデータベースにロードする。ロードの途中にも健全なデータベースを壊すかもしれない。

1)「DULを使う」で説明したステップでデータディクショナリーテーブル“source$”をエクスポートする。

2)新しいユーザーを作成して、健全なデータベースに登録して、一時テーブルスペースをしてください。

3)リンク、リソース、imp_full_databaseの権限を新しいユーザーに与える。

4)“source$”を新たに作成したモードにインポート/ロードする。

例えば:imp80 userid=newuser/passw file=d:\dul\scott_emp.dmp

log=d:\dul\impemp.txt full=y

5)今、テーブルの問合せから壊れたデータベースでpl/sql packages / procedures /functionsを再建できる。WebIvにこのようなPL / SQLを見つけだしてスクリプトを作成する。

同じステップでインデックス、制約、およびストレージ・パラメータを再建できる。該当するユーザーに再び権限を与えることもできる。

4.セグメントヘッダが壊れたときに、どうやってデータをエクスポートするでしょう

DULでデータブロックの情報を検索できないなら、データベースをスキャンして、マップを作成できる。データファイルからデータをエクスポートしたいなら、データベースをスキャンする必要がある。

(例を説明するためにセグメントヘッダから空っぽなブロックをコピする)

1)ふさわしい“init.dul”と“control.dul”を作成する。

2)テーブルをエクスポートする。これは必ず失敗する。セグメントヘッダには損害がある。

DUL> unload table scott.emp;

. unloading table EMP

DUL: Warning: Block is never used, block type is zero

DUL: Error: While checking tablespace 6 file 10 block 2

DUL: Error: While processing block ts#=6, file#=10, block#=2

DUL: Error: Could not read/parse segment header

0 rows unloaded

3)データベースをスキャンする

DUL> scan database;

tablespace 0, data file 1: 10239 blocks scanned

tablespace 6, data file 10: 2559 blocks scanned

4)DULにセグメントヘッダ情報ではなく、自身で作成したマップを使う必要があると説明してください。

DUL> alter session set use_scanned_extent_map = true;

Parameter altered

Session altered.

DUL> unload table scott.emp;

. unloading table EMP 14 rows unloaded

 

5.データファイルヘッダが壊れたときに、どうやってデータをエクスポートする。

データベースを起動するときに、データファイルヘッダの損害が示される。データベースが無事に起動できるが、テーブル問合せするときに、損害が示される。

以下の通りのエラ報告をもらえる:

ORACLE instance started.

Total System Global Area 11739136 bytes

Fixed Size 49152 bytes

Variable Size 7421952 bytes

Database Buffers 4194304 bytes

Redo Buffers 73728 bytes

Database mounted.

ORA-01122: database file 10 failed verification check

ORA-01110: data file 10: ‘D:\DATA\TRGT\DATAFILES\JUR1TRGT.DBF’

ORA-01251: Unknown File Header Version read for file number 10

 

6.システムテーブルスペースなしにどうやってデータをアンインストールするでしょう。

まず、そのアプリケーションとテーブルに十分な理解が必要としている。

列タイプはDULで当てられるが、テーブルも列の名もなくす。

どんな同じデータベースの古いシステムテーブルスペースも大した助けになる。

1)“init.dul”ファイルと“control.dul”ファイルを作成する。この場合にコントロールファイルがリカバリしたいファイルを含んでいるから、システムテーブルスペースが必要としていない。

2)DULで以下のコマンドをインポートしてください:

DUL> scan database;

data file 6 1280 blocks scanned

これでセグメントとセグメントマップも作成される。

3)DULコマンドで以下の操作を実行してください:

Data UnLoader: Release 8.0.5.3.0 – Internal Use Only – on Tue Aug 03 13:33:

Copyright (c) 1994/1999 Oracle Corporation, The Netherlands. All rights res

Loaded 4 segments

Loaded 2 extents

Extent map sorted

DUL> alter session set use_scanned_extent_map = true;

DUL> scan tables; (or scan extents;)

Scanning tables with segment header

Oid 1078 fno 6 bno 2 table number 0

UNLOAD TABLE T_O1078 ( C1 NUMBER, C2 UNKNOWN, C3 UNKNOWN )

STORAGE ( TABNO 0 EXTENTS( FILE 6 BLOCK 2));

Colno Seen MaxIntSz Null% C75% C100 Num% NiNu% Dat% Rid%

1 4 2 0% 0% 0% 100% 100% 0% 0%

2 4 10 0% 100% 100% 100% 0% 0% 0%

3 4 8 0% 100% 100% 100% 0% 0% 50%

“10” “ACCOUNTING” “NEW YORK”

“20” “RESEARCH” “DALLAS”

“30” “SALES” “CHICAGO”

“40” “OPERATIONS” “BOSTON”

Oid 1080 fno 6 bno 12 table number 0

UNLOAD TABLE T_O1080 ( C1 NUMBER, C2 UNKNOWN, C3 UNKNOWN, C4 NUMBER,

C5 DATE, C6 NUMBER, C7 NUMBER, C8 NUMBER )

STORAGE ( TABNO 0 EXTENTS( FILE 6 BLOCK 12));

Colno Seen MaxIntSz Null% C75% C100 Num% NiNu% Dat% Rid%

1 14 3 0% 0% 0% 100% 100% 0% 0%

2 14 6 0% 100% 100% 100% 0% 0% 21%

3 14 9 0% 100% 100% 100% 0% 0% 0%

4 14 3 7% 0% 0% 100% 100% 0% 0%

5 14 7 0% 0% 0% 0% 0% 100% 0%

6 14 3 0% 0% 0% 100% 100% 0% 0%

7 14 2 71% 0% 0% 100% 100% 0% 0%

8 14 2 0% 0% 0% 100% 100% 0% 0%

“7369” “SMITH” “CLERK” “7902” “17-DEC-1980 AD 00:00:00″ “800” “” “20”

“7499” “ALLEN” “SALESMAN” “7698” “20-FEB-1981 AD 00:00:00″ “1600” “300” “30”

“7521” “WARD” “SALESMAN” “7698” “22-FEB-1981 AD 00:00:00″ “1250” “500” “30”

“7566” “JONES” “MANAGER” “7839” “02-APR-1981 AD 00:00:00″ “2975” “” “20”

“7654” “MARTIN” “SALESMAN” “7698” “28-SEP-1981 AD 00:00:00″ “1250” “1400” “30”

Note : it might be best that you redirect the output to a logfile since

commands like the “scan tables” can produce a lot of output.

On Windows NT you can do the following command :

C:\> dul8 > c:\temp\scan_tables.txt

scan tables;

exit;

4)ステップ3のインポートでなくしたテーブルを見つけ出す。そして、unload文法があるのに、テーブルの名はまだT_0、列の名もC。データタイプは前のデータタイプにマッチしない。

特に“Oid 1078 fno 6 bno 2 table number 0”のような文字列を探す時に、oid = object id, will be used to unload the object目標idは目標をエクスポートするために使われる。

fno = (data)file number (データ)ファイル番号

bno = block number ブロック番号

5)“unload table”コマンドで見つけたテーブルをエクスポートする:

DUL> unload table dept (deptno number(2), dname varchar2(14),

loc varchar2(13)) storage (OBJNO 1078)

Unloading extent(s) of table DEPT 4 rows.

 

 

 

 

 

 

 

コメント:

DULディスクヘッドのコピー

ディスクヘッドのコピー

ディスクヘッドのコピー

最近はASMディスクヘッダエクストラなコピもあって、kfedとリカバリオプションで、本当のヘッダをリカバリできる。割り当てユニットのディフォルト大きさは4Kで、

位置

このコピはPSTの最後のブロックと格納されて、アロケーションユニット最後のブロックに意味する。各auに256ブロックがある。

Kfedリカバリ:

唯一な問題はディスクヘッダをなくした/壊れたことを確かめた時に、リカバリがすごく容易くなる:

$ kfed repair

Suの大きさが非標準であれば、以上の操作が失敗して、以下のようにインポートする:

KFED-00320: Invalid block num1 =  [3] , num2 =  [1] , error = [type_kfbh]

だが、これは予想内で、何の損害もないから。正確なauの大きさを指定すればいい。例えば、4MB AUのコマンドは:

$ kfed repair ausz=4194304

DUL

DULはヘッダコピを検索/使う(いつも?あるいは主なヘッダが壊れた場合に限る?)。もしヘッダが壊れたら、コピがまだ壊れていない場合に、kfedを使うことをアラームする?

参考

Bug 5061821 OSツールはASMディスクヘッダfixed 11.2.0.1,11.1.0.7,10.2.0.5を破壊できる。

注意:417687.1は今のディスクヘッダが壊れた後で新しいASMディスクヘッダを作成する。

rdbms/src/client/tools/kfed/kfed.c

 

 

 

 

DULはスキャンしたlobをエクスポートする。

LOBからLOBをエクスポートするほうがいいと思う

以下のようなことを確かめる必要がある:

  1. CLOBかBLOBか
  2. CLOBに対しての文字セット、シングルバイトまたはUCS16、バイトサイズ
  3. ブロックサイズ、ヘッダでのlob page#はfat page number
  4. なくしたページはすべてゼロになる
  5. サイズを知らないが、trailing zeroesを剥奪すればいい?

実行変更:

1. LOBセグメントIDを追加して、lobページ情報をスキャンする。つまり、スキャンしたlobページメモリーの配置はsegid,lobid,fatpageno(chunk#),version wrap, vsn base, ts#, file#, block#

 

やるべきこと:

  • すべてのLOBコマンドをエクスポートする。LOBセグメントでコマンドすべての一般的なプロパティを提供できる。
  • LOBセグメントからlobidを指定する。選択可能なサイズ、DBAリストでlobコマンドをエクスポートする。
  • エクスポートされたlobセグメントコマンドを分析する。
  • セグメントからエクスポートされたLOBコマンドを分析する。

考える必要があること:

  1. file#, block# をdba?pro no calculations, contra more difficult to readに変更する?

 

 

 

 

お客様とデータサルベージ操作の途中で、DULには問題が起きた。

dul4x86-linux.tar.gzエラ:version ‘GLIBC_2.11’ not found

 

dul4i386-linux.as3.tar.gzエラ::You need a more recent DUL version for this os.

 

クライアントLinuxバーション:2.6.32-400.33.2.el5uek

 

助けてください!!!

 

 

Linux有两个版本,这是第二个,被正常启动的。由于内建复制的保护,您必须确保从Bernard的网站上下载最新的版本。DUL大约每45天失效。

Linuxには二つのバーションがある。正確に起動されたのは二つ目。内蔵コピーを保護するために、Bernardから最新なバーションをダウンロードしてください。DULは約45日で使えなくなる。

 

 

 

大事な時でDULでproduction downデータベースからデータを抽出したい。

– データベースはNOARCHIVELOGモード/ Windows 64位プラットフォームにある。

– go lifeのせいで,使用可能なデータベースバックアップがない

-データベースが小さいが、とっても重要である。

-朝からメディア障害が出て本当のお客様のデータファイル以外のすべてのデータベースのデータファイルを壊した。

-システムテーブルスペースが100%に壊滅した。

-どこにもシステムテーブルスペースのバックアップもない、ましてテストシステムは新たなデータベースのために作成されたから、目標ID,rfileも違っている。

以下の内容を試した:

  1. システムデータファイルでデータをエクスポートする。(システムデータファイルが壊れたから、bootstrapできない)。
  2. システムデータファイルでTESTからデータをエクスポートする(bootstrapできたがエクスポートできない。rfile#,TS#にマッチできないから、予想できたが、試しがいがある)。
  3. 実際のデータだけでデータファイルをエクスポートする、scaned_tablesを作成できた。お客様の要請に応じてテーブルのリストを提供してmapしたが、お客様が正確な情報を提供できるかどうかにはまだ知らない。

どんなアドレスも大歓迎、例えば:

- どうやって壊れたシステムテーブルスペースのデータファイルをリカバリして、データをエクスポートするでしょうか

– rfile#, ts#及び目標idがミスマッチした場合に。どうやってTESTからシステムデータファイルを使うでしょうか(異なるデータベースをインストール)

 

 

沪ICP备14014813号-2

沪公网安备 31010802001379号