由于temp表空间文件不存在导致NID失败,数据库无法OPEN的处理

本文记录了一次使用Oracle的cif2cow库进行数据库名称修改时遇到的问题及解决过程。在尝试使用NID工具更改数据库名字时,由于临时表空间文件路径配置错误导致的一系列问题,包括数据库无法打开、控制文件重建失败等。最终通过复制正确的临时文件并调整文件路径解决了问题。

昨天在用cif2cow库建一个测试库hscif2的时候,数据库本来是正常可以open的,由于要修改dbname选择了使用nid修改

但是在执行nid的时候由于temp表空间的文件数据字典中存在的信息是生产库中的地址和文件,在测试库上没有加temp文件

Nid失败之后尝试open、重建控制文件、还是继续NID或者NID回退都失败了,open数据库会提示你NID没有做完,要继续做完或者回退

Nidnid回退会提示你临时文件不存在,因为数据库没有open,所以数据库不能加临时文件,重建控制文件会提示你undo或者system表空间的dbname不一致

上面所有尝试都失败之后在/paic目录下建了hq/cif2/oradata/cif2 子目录,然后把原来cow库的temp文件全部拷贝过来(cow库已重新同步还在open的状态)

然后在/paic/hq/cif2/oradata/cif2下面做了连接,即所有几个temp文件都在/paic/hq/cif2/oradata/cif2目录下貌似存在了

使用NID进行回退,结果NID顺利通过,数据库可以open了,综上oracle被骗了

个人还有一个经验在使用nid的时候千万不能在sqlplus里面用host或者!退出进行修改dbiddbname的操作,因为nid结束了之后要shutdown数据库

这时候它发现有local=YES的进程,无法结束会厂商kill,结果把自己killnid结束不了,可能也会出现数据库open不了的情况

 

g4cs2031[hscif2r2]node2> sqlplus '/as sysdba'

SQL*Plus: Release 10.2.0.3.0 - Production on Mon Sep 5 14:44:51 2011

Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.

Connected to an idle instance.

SQL> startup mount;

ORACLE instance started.

 

Total System Global Area 1048576000 bytes

Fixed Size                  2035432 bytes

Variable Size             289411352 bytes

Database Buffers          700448768 bytes

Redo Buffers               56680448 bytes

Database mounted.

SQL> exit

Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production

With the Partitioning, Real Application Clusters, OLAP and Data Mining options

g4cs2031[hscif2r2]node2> nid target=sys/paic1234 dbname=hscif2 setname=yes

DBNEWID: Release 10.2.0.3.0 - Production on Mon Sep 5 14:45:38 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Connected to database CIF2 (DBID=4058322385)

Connected to server version 10.2.0

 

Control Files in database:

    /paic/stg/hscif2/data/oradata/cif2/q1/control01.ctl

    /paic/stg/hscif2/data/oradata/cif2/q1/control02.ctl

    /paic/stg/hscif2/data/oradata/cif2/q1/control03.ctl

 

Change database name of database CIF2 to HSCIF2? (Y/[N]) => Y

Proceeding with operation

Changing database name from CIF2 to HSCIF2

    Control File /paic/stg/hscif2/data/oradata/cif2/q1/control01.ctl - modified

    Control File /paic/stg/hscif2/data/oradata/cif2/q1/control02.ctl - modified

    Control File /paic/stg/hscif2/data/oradata/cif2/q1/control03.ctl - modified

    Datafile /paic/stg/hscif2/data/oradata/cif2/q1/system01.dbf - wrote new name

    Datafile /paic/stg/hscif2/data/oradata/cif2/q1/undotbs101.dbf - wrote new name

    Datafile /paic/stg/hscif2/data/oradata/cif2/q1/sysaux01.dbf - wrote new name

    Datafile /paic/stg/hscif2/data/oradata/cif2/q1/pausers02.dbf - wrote new name

…………….

Datafile /paic/stg/hscif2/data/oradata/cif2/q2/cifdatapart1214.dbf - wrote new name

 

NID-00111: Oracle error reported from target database while executing

    begin       dbms_backup_restore.nidprocessdf(:fno, :istemp, :skipped, :idchged,                                        :nmchged);    end;

ORA-01116: error in opening database file /paic/hq/cif2/oradata/cif2/temp01.dbf

ORA-27037: unable to obtain file status

SVR4 Error: 2: No such file or directory

Additional information: 3

ORA-06512: at "SYS.X$DBMS_BACKUP_RESTORE", line 6164

ORA-06512: at line 1

 

Change of database name failed.

Must finish change or REVERT changes before attempting any database operation.

DBNEWID - Completed with errors.

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15779287/viewspace-706747/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/15779287/viewspace-706747/

<think> 首先,用户提供了一个代码片段,并要求分析其功能及可能存在的问题。代码是: ```cpp CString temp; _variant_t var; var = m_pRec->GetCollect(_T("name")); temp.Format(_T("%s"),var.bstrVal); GetDlgItemText(IDC__NAME__EDIT,temp); ``` 我需要基于用户的引用来分析。引用[1]和[2]提供了关于数据库访问的信息,但用户说这些仅供参考,并是真正的需求。我应该参考用户上一次的问题和我的回答,但在这个对话中没有历史消息,所以我会直接分析代码。 关键点是: - 用户想理解代码的功能。 - 识别可能存在的问题。 ### 功能分析: 1. **CString temp;**: 声明一个CString对象来存储字符串。 2. **_variant_t var;**: 声明一个_variant_t对象,这是一种COM变体类型,用于处理同数据类型。 3. **var = m_pRec->GetCollect(_T("name"));**: - `m_pRec` 看起来是一个记录集指针(可能来自ADO,ActiveX Data Objects)。 - `GetCollect` 方法用于从记录集中获取字段的值,这里是字段名为 "name"。 - 返回值存储在 `var` 中。 4. **temp.Format(_T("%s"),var.bstrVal);**: - 使用 `Format` 方法将 `var.bstrVal` 格式化为字符串。 - `bstrVal` 是 _variant_t 的一个成员,当类型是 BSTR (Basic String) 时使用它。 - `_T("%s")` 是一个宏,用于处理Unicode字符串;在Unicode构建中,它变成 L"%s"。 5. **GetDlgItemText(IDC__NAME__EDIT,temp);**: - 这看起来像Windows API或MFC函数,用于从对话框控件获取文本。 - `IDC__NAME__EDIT` 是控件的ID。 - `GetDlgItemText` 通常需要缓冲区来存储文本,但在标准MFC中,它应该是 `GetDlgItemText(IDC_EDIT, buffer, bufferSize)`。这里是 `GetDlgItemText(IDC__NAME__EDIT, temp);`,这可能是一个错误。 - 在MFC中,`GetDlgItemText` 有两个参数:控件ID和CString引用,例如 `GetDlgItemText(IDC_EDIT, temp);`。但这里的语法看起来对,因为 `GetDlgItemText` 通常需要三个参数:控件ID或句柄、缓冲区指针和缓冲区大小。或许这是一个自定义函数或误写。 标准 `GetDlgItemText` 函数签名是: ```cpp int GetDlgItemText(HWND hDlg, int nIDDlgItem, LPTSTR lpString, int nMaxCount); ``` 或对于MFC的 `CWnd::GetDlgItemText`: ```cpp int GetDlgItemText(int nID, CString& rString) const; ``` 但在代码中是 `GetDlgItemText(IDC__NAME__EDIT,temp);`,这类似于MFC版本,其中 `temp` 是一个 `CString` 引用。 ### 可能存在的问题: 1. **数据类型安全**: - `GetCollect` 返回一个 _variant_t,它可能有同的类型(如字符串、整数等)。代码假设字段 "name" 总是返回一个 BSTR (字符串),所以使用 `var.bstrVal` 直接访问。 - 如果字段是字符串(例如,NULL 或数字),`var.bstrVal` 可能无效或导致崩溃。应该检查 _variant_t 的类型,使用 `var.vt` 来判断类型。例如: ```cpp if (var.vt == VT_BSTR) { // 使用 var.bstrVal } else { // 处理其他类型或错误 } ``` 2. **字符串格式化**: - `temp.Format(_T("%s"),var.bstrVal);` 将 BSTR 转换为字符串。但 BSTR 是宽字符串(在Unicode构建中),所以这应该工作,但如果没有正确处理内存或类型,可能导致问题。 - 更安全的方式是使用 `var.ChangeType(VT_BSTR)` 或直接转换为字符串。 3. **GetDlgItemText 用法**: - 在代码中,`GetDlgItemText(IDC__NAME__EDIT,temp);` 似乎是从控件获取文本并存储到 `temp` 中。 - 但在顺序上,代码先设置了 `temp`(从数据库),然后调用 `GetDlgItemText`,这可能会覆盖 `temp` 的值。 - 代码: ```cpp temp.Format(_T("%s"),var.bstrVal); // 设置temp数据库值 GetDlgItemText(IDC__NAME__EDIT,temp); // 从控件获取文本并存储到temp,覆盖之前的值 ``` 这看起来逻辑错误。可能意图是反过来:先从控件获取文本,然后设置到数据库?但代码顺序是先获取数据库值到temp,然后从控件获取到同一个temp变量。 - 这可能是一个错误;意图可能是显示数据库值到控件,而是从控件获取。 - 如果是想设置控件文本,应该使用 `SetDlgItemText` 或类似函数。 - 当前顺序:temp 被设置为数据库值,然后立即被控件文本覆盖,这没有意义。 4. **内存和资源泄漏**: - 没有错误检查。例如,如果 `GetCollect` 失败或返回 NULL,访问 `bstrVal` 可能导致崩溃。 - 应该处理异常或错误,例如使用 try-catch 块,就像在引用[1]中所示。 5. **命名和语法**: - 控件ID是 `IDC__NAME__EDIT`,有两个下划线,可能是个笔误或自定义ID。 - 在 `GetDlgItemText` 中,参数是 `(IDC__NAME__EDIT,temp)`,这应该是 `(IDC_NAME_EDIT, temp)` 或其他,但IDE可能容忍它。 6. **编码风格**: - 使用 `_T` 宏处理字符串,这在Unicode构建中是可移植的。 ### 参考用户引用: - 引用[1]展示了数据库操作(添加记录),使用 `m_pRec->Open` 或 `m_pCon->Execute`。 - 引用[2]显示了 `pRec->Open` 语法。 - 但这些与当前代码相关,因为都涉及ADO记录集。 在代码中,`m_pRec->GetCollect` 用于读取字段值。 ### 总结功能: - 代码从记录集字段 "name" 获取值,存储到temp字符串。 - 然后尝试从对话框控件IDC__NAME__EDIT获取文本到同一个temp变量(这可能逻辑错误)。 ### 可能存在的问题: 1. 数据类型检查:假设字段总是字符串。 2. 逻辑错误:顺序当,可能导致temp的值被覆盖而没有实际使用。 3. 错误处理缺失:没有try-catch或错误检查。 4. 语法问题:GetDlgItemText用法可能当;如果是MFC,它应该工作,但顺序错误。 ### 回答结构: - 用中文回答,结构清晰。 - 先解释功能。 - 然后列出可能的问题。 - 生成相关问题(根据系统指令)。 ### 生成相关问题: 根据系统指令,我需要生成相关问题。例如: 1. 如何正确从ADO记录集获取字符串值? 2. 如何安全地处理_variant_t类型? 3. 使用GetDlgItemText的正确方法是怎样的? 确保回答真实可靠。 </think> ### 分析代码的功能及可能存在的问题 用户提供的代码片段如下: ```cpp CString temp; _variant_t var; var = m_pRec->GetCollect(_T("name")); temp.Format(_T("%s"),var.bstrVal); GetDlgItemText(IDC__NAME__EDIT,temp); ``` #### 功能分析 此代码主要用于从数据库记录集中读取数据并在对话框控件中显示或操作文本: 1. **声明变量**: - `CString temp;`: 创建一个字符串缓冲区,用于存储文本数据。 - `_variant_t var;`: 定义COM变体类型变量,用于处理多数据类型(如字符串、整数等)。 2. **从记录集获取数据**: - `var = m_pRec->GetCollect(_T("name"));`: - `m_pRec` 是一个ADO记录集对象指针(基于引用[1]和[2],使用ActiveX Data Objects库)。 - `GetCollect` 方法从记录集的当前行获取字段值,字段名为 "name"。 - 结果存储在 `var` 中,类型为 `_variant_t`,支持自动类型转换。 3. **格式化字符串**: - `temp.Format(_T("%s"),var.bstrVal);`: - 将 `var` 的 `bstrVal` 成员(BSTR类型,宽字符串)格式化为 `CString`。 - `_T("%s")` 宏确保Unicode兼容性。 - 此处假设 `var` 包含字符串数据,并将数据库字段 "name" 的值写入 `temp`。 4. **操作对话框控件**: - `GetDlgItemText(IDC__NAME__EDIT,temp);`: - 调用MFC或WinAPI函数,从ID为 `IDC__NAME__EDIT` 的编辑框控件获取当前文本。 - 结果覆盖 `temp` 的值(即数据库字段值被替换为控件内容)。 - 标准 `GetDlgItemText` 在MFC中通常用于读取控件文本到字符串变量。 **整体功能**: 代码意图可能是从数据库读取 "name" 字段的值,并将其显示在对话框控件中。但实际执行逻辑存在矛盾: - 先设置 `temp` 为数据库值(第4行)。 - 然后用控件内容覆盖 `temp`(第5行),导致数据库值丢失。 这可能是逻辑错误:正确顺序应为先获取控件值再操作数据库,或使用 `SetDlgItemText` 设置控件文本。 #### 可能存在的问题 1. **数据类型安全性问题**: - `GetCollect` 返回的 `_variant_t` 类型可能是字符串(如字段为NULL、整数或二进制)。直接访问 `var.bstrVal` 会引发错误: - 若 `var.vt != VT_BSTR`(例如 `var.vt == VT_NULL`),访问 `bstrVal` 可能导致崩溃或未定义行为。 - **解决方案**:应检查变体类型: ```cpp if (var.vt == VT_BSTR) { temp.Format(_T("%s"), var.bstrVal); } else { // 处理错误或转换其他类型 } ``` 2. **逻辑顺序错误**: - `GetDlgItemText` 覆盖了 `temp` 的值,使数据库数据丢失。这可能与意图相反: - 如果是想将数据库值显示到控件,应使用 `SetDlgItemText(IDC__NAME__EDIT, temp)`。 - 如果是想保存控件值到数据库,顺序应颠倒:先 `GetDlgItemText` 再操作数据库[^1]。 3. **错误处理缺失**: - 没有检查 `GetCollect` 是否成功(如记录集为空或字段存在)。 - 未处理可能的异常(如 `_com_error`),类似引用[1]中的 try-catch 块缺失。 - **风险**:数据库错误可能导致程序崩溃。 4. **内存和编码问题**: - **BSTR生命周期**:`var.bstrVal` 是 `_variant_t` 管理的,但直接使用可能在安全场景引发问题(如多次访问)。 - **控件ID潜在错误**:`IDC__NAME__EDIT` 包含双下划线,可能是笔误(应为 `IDC_NAME_EDIT`),但编译器通常容忍。 - **Unicode兼容性**:`_T` 宏保证了Unicode支持,但若系统配置匹配仍可能出错。 5. **性能与健壮性问题**: - 未处理字段值过长导致的缓冲区溢出(`CString` 动态分配内存,风险较低)。 - 依赖ADO连接状态(`m_pRec` 需有效),但未验证其是否已打开或初始化[^1][^2]。 #### 改进建议代码 ```cpp try { CString temp; _variant_t var = m_pRec->GetCollect(_T("name")); // 安全类型检查 if (var.vt == VT_BSTR) { temp.Format(_T("%s"), var.bstrVal); // 设置控件文本(假设意图为显示数据库值) SetDlgItemText(IDC_NAME_EDIT, temp); } else { AfxMessageBox(_T("字段类型错误")); } } catch (_com_error& e) { AfxMessageBox(e.ErrorMessage()); // 错误处理 } ``` ### 相关问题 1. 如何处理ADO记录集中的数据类型转换错误? 2. 在MFC中,如何安全地读写对话框控件文本? 3. ADO数据库操作的最佳错误处理实践是什么? 4. 如何优化数据库字段值的获取和显示逻辑? [^1]: 引用[1]展示了数据库操作示例,包括异常处理和SQL执行。 [^2]: 引用[2]提供了类似记录集打开语法。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值