🚀 使用AI代理的Oracle数据库自主迁移(MCP&SQLcl)
务实、久经考验的代理DBA工作流程 --构建真正的解决方案需要面对基础设施的现实,而不仅仅是理论。该项目既展示了成功,也展示了工程权衡,包括实际环境约束导致的关键。
______________________________________________________________________
🔥 更新(2026-02-18):实现了对Oracle钱包的原生支持! 虽然主分支表现出强大的 JCEKS解决方法 对于GitHub Copilot,我成功地设计了一个协议修复程序,允许 克劳德代码 使用 原生Oracle钱包(SEPS) 直接。 🚀 在此处查看突破性解决方案: 👉 转到v2:克劳德代码+本地钱包修复和协议代理
______________________________________________________________________
🛡️ 更新(2016年2月24日):第3部分——使用Gemini 3 Pro进行自主DevSecOps! 我在游戏中引入了第三个代理(谷歌反重力/双子座)。这一次,代理被赋予了一项关键的业务任务:安全 生产数据库的热克隆 结合即时, 敏感数据的数据库内屏蔽(PII/GDPR),零数据泄漏到云端。 🚀 在此处查看脚本和完整操作演练: 👉 转到v3:Gemini+DevSecOps(克隆和数据屏蔽)
______________________________________________________________________
📖 目录
______________________________________________________________________
📖 关于项目
这个项目是 概念验证(PoC) 演示使用 模型上下文协议(MCP) 通过自主的AI代理——VSCode中的GitHub Copilot来管理Oracle数据库。
所执行的操作是 零停机的PDB(可插拔数据库)热重定位 --从CDB1到CDB2实例,通过 拉 使用数据库链接的方法 AVAILABILITY MAX 条款。代理在没有手动登录和向语言模型(LLM)传递密码的情况下运行。
🎯 这不是普通的管理。这是一个 L5级代理DBA工作流程.
您键入: *“将HR_PDB数据库移动到CDB2”*.\ Agent计划、执行、遇到错误, 自主诊断、修复并完成任务,然后在不知道密码的情况下报告结果。
______________________________________________________________________
🔑 关键创新
1.⭐ 零密码LLM交互——SQLcl JCEKS存储
语言模型(Copilot) 永远看不到密码。代理向SQLcl发送命令 connect ai-cdb1.SQLcl从本地加密的JCEKS存储中读取密码并建立连接,而不涉及任何LLM。
# DBA configures once (the only moment the password appears in the terminal):
sql /nolog
SQL> connect -save ai-cdb1 c##mcp_ai/SecretPassword@CDB1
SQL> connect -save ai-cdb2 c##mcp_ai/SecretPassword@CDB2
# The AI Agent connects from now on like this:
sql -mcp ai-cdb1 # ← no password in the call — LLM never sees it为什么选择JCEKS而不是Oracle钱包? Oracle钱包使用VSCode/JDBC瘦失败。这是该项目的核心发现——参见 工程枢纽 部分。
2.热重定位——零停机时间(最大可用性)
而不是经典的冷迁移(关闭→ 拔掉→ Drop → Plug),代理执行了 热门搬迁 --源数据库保留在其中的操作 READ WRITE 模式贯穿始终。数据和重做日志同步发生在后台。停机时间以秒为单位,而不是分钟。
-- One command, executed EXCLUSIVELY on CDB2 (PULL method):
CREATE PLUGGABLE DATABASE hr_pdb
FROM hr_pdb@cdb1_link
RELOCATE AVAILABILITY MAX;3.人工智能自愈——自主实时调试
代理 独立地 在没有DBA干预的情况下诊断并修复了两个Oracle错误:
ORA-00922→ 更正了SQL语法(选项太多)ORA-01031(通过ORA-17628) → 了解Hot Relocate需要SYSDBA读取联机重做日志,并请求授予权限
这是智能人工智能在IT领域的圣杯。
______________________________________________________________________
⚠️ 工程支点:钱包→ JCEKS——该项目的核心发现
如果您通过搜索“SQLcl MCP钱包不工作”或“ORA-01017 VSCode MCP”找到此页面,则本节适合您。世界各地的建筑师都在努力解决这个问题。
起点:Oracle钱包(SEPS)——理论
标准方法是 Oracle钱包(SEPS) --DBA保存密码的加密存储。客户端通过TNS别名连接,无需提供密码。
# Wallet configured and WORKS correctly from the terminal:
mkstore -wrl /home/oracle/wallet -createCredential CDB1 c##mcp_ai "passwd"
mkstore -wrl /home/oracle/wallet -createCredential CDB2 c##mcp_ai "passwd"
mkstore -wrl /home/oracle/wallet -listCredential
# 4: CDB2 c##mcp_ai
# 3: CDB1 c##mcp_ai
# 2: CDB2_SYS SYS
# 1: CDB1_SYS SYS
sql /@CDB1_SYS AS SYSDBA # ← connects without a password from the terminal ✅碰壁:VSCode中的JDBC瘦驱动程序
尝试通过SQLcl MCP的钱包保存连接:
SQL> connect -save ai-cdb1 /@CDB1
Name: ai-cdb1
Connect String: CDB1
User: ← EMPTY!
Password: not saved ← EMPTY!
Connected. ← apparent success, followed shortly by: ORA-01017红旗: User: (empty)JDBC驱动程序未从钱包中读取凭据。
🔬 《Deep Dive》:为什么JDBC瘦忽略了cwallet.sso?
当您使用该命令时 connect -save ai-cdb1 /@CDB1,你依赖司机使用化名 CDB1,咨询 sqlnet.ora 文件,查找由定义的钱包 mkstore,并提取密码 c##mcp_ai 从它。
在 终端 (在本地Oracle OCI客户端运行的地方),这可以完美地工作。然而 瘦驱动嵌入在VS Code插件的封闭Java进程中的,非常“抵制”读取外部钱包(SEPS)中的空凭据,除非有特殊的JVM标志(-Doracle.net.wallet_location)传递给Java虚拟机。扩展主机没有它们,因此它只是向数据库发送了一个“空”用户,侦听器立即拒绝了该用户。
Oracle提供 两个完全不同 连接驱动程序:
| 特性 | OCI客户端(本机) | JDBC精简驱动程序 |
|---|---|---|
| 环境 | Linux终端、sqlplus | Java进程、VSCode扩展主机 |
| 读cwallet.sso? | ✅ 是--通过 sqlnet.ora | ⚠️ 仅具有显式JVM标志 |
| 必需的JVM标志 | 无 | -Doracle.net.wallet_location=/path |
| VSCode扩展主机 | 未使用 | 已使用-- 但没有这面旗! |
VSCode内部故障剖析:
flowchart TD
subgraph FAIL ["❌ VSCode Extension Host — closed Java process"]
direction TB
A["⚙️ SQLcl JDBC Thin Driver"]
A --> B["Tries to read sqlnet.ora..."]
B --> C["Looks for WALLET_LOCATION"]
C --> D["Missing flag -Doracle.net.wallet_location\nin Extension Host JVM"]
D --> E["We cannot set it\nfrom the plugin interface!"]
E --> F["Sends EMPTY user"]
F --> G["🔴 ORA-01017: invalid username/password"]
end
subgraph OK ["✅ Terminal — native OCI Client (C libraries)"]
direction TB
H["sql /@CDB1"]
H --> I["OCI Client (C libraries)"]
I --> J["Reads sqlnet.ora natively"]
J --> K["Finds wallet\n(/home/oracle/wallet/cwallet.sso)"]
K --> L["Decrypts password for c##mcp_ai"]
L --> M["🟢 Connected ✅"]
end
style G fill:#fdd,stroke:#cc0000,color:#cc0000,stroke-width:2px
style M fill:#dfd,stroke:#2d862d,color:#1a5c1a,stroke-width:2px
style FAIL fill:#fff5f5,stroke:#cc0000,stroke-dasharray:5 5
style OK fill:#f5fff5,stroke:#2d862d,stroke-dasharray:5 5
style D fill:#fff3cd,stroke:#ff9900
style E fill:#fff3cd,stroke:#ff9900✅ 解决方案:SQLcl内部保险库(JCEKS)
我们使用 SQLcl内置的加密凭据存储它的工作原理同样安全——在Linux上,密码是用机器绑定的AES密钥加密的,人工智能永远不会看到它,JDBC驱动程序可以动态解码,没有任何问题。
-- Correct approach for VSCode MCP:
sql /nolog
SQL> connect -save ai-cdb1 c##mcp_ai/StrongPasswordForAI_2026#@CDB1
-- Name: ai-cdb1 | User: c##mcp_ai | Connected ✅ — password saved in JCEKS!
SQL> connect -save ai-cdb2 c##mcp_ai/StrongPasswordForAI_2026#@CDB2
-- Name: ai-cdb2 | User: c##mcp_ai | Connected ✅SQLcl在幕后做了什么:
- 生成绑定到计算机的唯一AES密钥
- 在中加密密码 JCEKS 格式(Java KeyStore--企业标准)
- 保存到
~/.sqlcl/connections.json(一个干净的文件,没有明文密码) - JDBC精简版
sql -mcp ai-cdb1阅读JCEKS 天生地 --不需要JVM标志
工程结论:
问题是,当地人 cwallet.sso Linux终端使用的基于C的库(OCI)完全理解钱包。另一方面,VS代码扩展主机中的内部JDBC瘦驱动程序需要显式的JVM参数,我们只需 无法访问 从Microsoft和Oracle插件界面。SQLcl凭据存储解决方法仍然是 企业级机制 --在幕后,SQLcl生成一个唯一的AES密钥,并以JCEKS格式对密码进行加密。安全目标(LLM看不到密码)已实现。______________________________________________________________________
🏗 架构——实际实施
构件图
graph TD
User["👤 KCB Kris (DBA)"] -->|"Prompt: Migrate HR_PDB to CDB2"| Agent["🤖 GitHub Copilot
(VSCode MCP Client)"]
subgraph SecureEnv ["🔒 Secure Environment — VSCode Extension Host (Java)"]
Agent |"MCP Protocol JSON-RPC"| SQLcl["⚙️ SQLcl -mcp ai-cdb2
(JDBC Thin Driver)"]
SQLcl -->|"Credential Lookup"| JCEKS["🔐 SQLcl JCEKS Store
(~/.sqlcl/connections.json)
AES encrypted · machine-bound"]
JCEKS -.->|"Decrypted natively by JDBC
No JVM flags needed ✅"| SQLcl
note_wallet["⚠️ cwallet.sso DOES NOT work here
JDBC Thin: missing flag -Doracle.net.wallet_location
in Extension Host JVM (inaccessible from the plugin)"]
end
subgraph DBInfra ["🗄️ Database Infrastructure"]
SQLcl |"JDBC / SQL*Net"| CDB2[("📦 CDB2 (target)
connection: ai-cdb2")]
CDB2 |"DB Link: cdb1_link
c##mcp_ai@CDB1"| CDB1[("📦 CDB1 (source)
connection: ai-cdb1
+ HR_PDB")]
CDB1 -.->|"Redo Stream + Datafiles
AVAILABILITY MAX
HR_PDB open R/W the entire time!"| CDB2
end
style JCEKS fill:#dfd,stroke:#2d862d,stroke-width:4px
style note_wallet fill:#fdd,stroke:#cc0000,stroke-width:1px
style Agent fill:#f9f,stroke:#333,stroke-width:2px
style SQLcl fill:#bbf,stroke:#333,stroke-width:2px
style CDB2 fill:#ddf,stroke:#333,stroke-width:2px序列图——包括错误和自愈的实际流程
sequenceDiagram
autonumber
participant DBA as 👤 DBA (Kris)
participant AI as 🤖 Copilot (MCP)
participant JCEKS as 🔐 JCEKS Store
participant CDB2 as 🗄️ CDB2 (target)
participant CDB1 as 🗄️ CDB1 (source)
Note over DBA,JCEKS: ══ SETUP: DBA configures once ══
DBA->>AI: connect -save ai-cdb1 c#35;#35;mcp_ai/pass@CDB1
AI->>JCEKS: Encrypt with machine AES key ✅
DBA->>AI: connect -save ai-cdb2 c#35;#35;mcp_ai/pass@CDB2
AI->>JCEKS: Encrypt with machine AES key ✅
Note over DBA,CDB1: ══ MIGRATION: Autonomous Agent ══
DBA->>AI: "Move HR_PDB from CDB1 to CDB2 (Hot Relocate)"
AI->>JCEKS: Resolve ai-cdb2
JCEKS-->>AI: Decrypt (native JDBC integration ✅)
AI->>CDB2: CONNECT ai-cdb2
AI->>CDB2: CREATE DATABASE LINK cdb1_link
CONNECT TO c#35;#35;mcp_ai...USING 'CDB1'
CDB2->>CDB1: SELECT * FROM dual@cdb1_link (test)
CDB1-->>CDB2: X — link works ✅
AI->>CDB2: CREATE PLUGGABLE DATABASE hr_pdb
FROM hr_pdb@cdb1_link
RELOCATE AVAILABILITY MAX PARALLEL 4 WITH SERVICES
CDB2-->>AI: ❌ ORA-00922: missing or invalid option
Note over AI: 🔄 SELF-HEALING #1
Analyzes error, removes unsupported clauses
AI->>CDB2: CREATE PLUGGABLE DATABASE hr_pdb
FROM hr_pdb@cdb1_link RELOCATE AVAILABILITY MAX
CDB2->>CDB1: Privilege verification via DB Link
CDB1-->>CDB2: ❌ ORA-17628 → ORA-01031: insufficient privileges
Note over AI: 🔄 SELF-HEALING #2
Diagnoses: Hot Relocate reads Online Redo Logs
over the network → SYSDBA required on source
AI-->>DBA: "On CDB1, grant c#35;#35;mcp_ai: GRANT SYSDBA..."
DBA->>CDB1: GRANT SYSDBA TO c#35;#35;mcp_ai CONTAINER=ALL
DBA->>AI: "Done! Continue."
AI->>CDB2: CREATE PLUGGABLE DATABASE hr_pdb
FROM hr_pdb@cdb1_link RELOCATE AVAILABILITY MAX
CDB1-->>CDB2: 🔄 Datafiles + Redo Stream (HR_PDB open R/W!)
CDB2-->>AI: ✅ Pluggable database created
Note over CDB1: HR_PDB AUTOMATICALLY removed
by Oracle engine after successful RELOCATE
AI->>CDB2: ALTER PLUGGABLE DATABASE hr_pdb OPEN
AI->>CDB2: SELECT name, open_mode FROM v$database
CDB2-->>AI: HR_PDB | READ WRITE ✅
AI-->>DBA: "✅ Migration complete. HR_PDB is open in CDB2."______________________________________________________________________
🔧 需求
| 组件 | 版本 | 注释 |
|---|---|---|
| Oracle数据库 | 26ai(23ai+) | 多租户架构,CDB/PDB |
| SQLcl | 25.2或更新版本 | 支持 -mcp 旗和 connect -save |
| Java | JDK 11+ | 与SQLcl捆绑在一起 |
| AI客户端 | VSCode+GitHub副本 | 或者:Claude Desktop、Cline、Cursor |
| 操作系统 | Oracle Linux 8/9,RHEL | 64位,最小8GB RAM |
环境验证
# SQLcl (MUST be 25.2+)
sql -version
# SQLcl: Release 25.2.0.0 Production
# Databases
ps -ef | grep pmon
# ora_pmon_CDB1, ora_pmon_CDB2
# Listener
lsnrctl status
# Service "CDB1" has 1 instance(s)
# Service "CDB2" has 1 instance(s)______________________________________________________________________
⚙️ 逐步配置
第一步:安装Oracle 26ai
# Extract ORACLE_HOME
mkdir -p /u01/app/oracle/product/26.0.0/dbhome_1
cd /u01/app/oracle/product/26.0.0/dbhome_1
unzip -q /home/oracle/ora26aihome.zip
# Silent installation using a response file (no GUI)
./runInstaller -silent \
-responseFile /home/oracle/db_home_fs_26ai.rsp \
-ignorePrereqFailure响应文件: config/oracle/db_home_fs_26ai.rsp
步骤2:创建CDB1和CDB2
chmod 700 scripts/installation/create_cdb_26ai_v3.sh
./scripts/installation/create_cdb_26ai_v3.sh脚本的作用:
- CDB1 与PDB
HR_PDB(迁移来源) - CDB2 空(迁移目标)
totalMemory 2560--2.5GB的硬分配(平衡SGA+矢量运算)vector_memory_size=256M--在DBCA期间减少(为安装过程提供更多空间)- FRA:12GB(消除DBT-06801警告)
optimizer_adaptive_plans=true,-ignorePreReqs
如果DBCA失败--清理:
sudo ./scripts/installation/cleanup_failed_dbca.sh
# Cleans oratab, data files, dbs/*CDB1*, dbs/*CDB2*步骤3:网络配置(侦听器+TNS)
bash scripts/installation/setup_network_26ai.sh生成 listener.ora 和 tnsnames.ora (CDB1、CDB2、HR_PDB)重新启动侦听器。LREG过程将在约60秒内自动注册数据库。
lsnrctl services | grep -E "CDB1|CDB2|HR_PDB"步骤4:启用ARCHIVELOG模式
-- Execute for CDB1:
cdb1 -- environment alias
sqlplus / as sysdba
@scripts/database/enable_archivelog_mode.sql
-- Expected output:
-- Database log mode: Archive Mode
-- Automatic archival: Enabled
-- Archive destination: USE_DB_RECOVERY_FILE_DEST
-- Repeat for CDB2
cdb2
sqlplus / as sysdba
@scripts/database/enable_archivelog_mode.sql步骤5:创建AI用户(c##mcp_AI)
执行条件 CDB1和CDB2:
-- scripts/security/AI_PDB_Migration_Role.sql
-- (FINAL VERSION — with full migration privileges)
CREATE USER c##mcp_ai IDENTIFIED BY StrongPasswordForAI_2026# CONTAINER=ALL;
-- Privileges for PDB operations
GRANT CREATE SESSION, CREATE DATABASE LINK TO c##mcp_ai CONTAINER=ALL;
GRANT CREATE PLUGGABLE DATABASE, ALTER PLUGGABLE DATABASE,
DROP PLUGGABLE DATABASE TO c##mcp_ai CONTAINER=ALL;
GRANT CREATE ANY DIRECTORY, DROP ANY DIRECTORY TO c##mcp_ai CONTAINER=ALL;
-- Administrative roles (no SYSDBA for standard operations)
GRANT DBA, CDB_DBA TO c##mcp_ai CONTAINER=ALL;
GRANT SELECT ANY DICTIONARY TO c##mcp_ai CONTAINER=ALL;
PROMPT Account c##mcp_ai ready for PDB automation!步骤6:Oracle钱包——用于终端(可选,流程文档)
上下文:钱包已按计划配置。它在终端(OCI客户端)上正常工作。 VSCode/MCP失败 --由JCEKS代替(步骤7)。
mkdir -p /home/oracle/wallet
mkstore -wrl /home/oracle/wallet -create
# Credentials for SYS (for terminal-based administration)
mkstore -wrl /home/oracle/wallet -createCredential CDB1_SYS SYS "SYSpassword"
mkstore -wrl /home/oracle/wallet -createCredential CDB2_SYS SYS "SYSpassword"
# Credentials for c##mcp_ai (wallet attempt → failed with VSCode)
mkstore -wrl /home/oracle/wallet -createCredential CDB1 c##mcp_ai "AIpassword"
mkstore -wrl /home/oracle/wallet -createCredential CDB2 c##mcp_ai "AIpassword"
# Verify wallet contents:
mkstore -wrl /home/oracle/wallet -listCredential
# 4: CDB2 c##mcp_ai
# 3: CDB1 c##mcp_ai
# 2: CDB2_SYS SYS
# 1: CDB1_SYS SYS
# Test from terminal (OCI Client — works!):
sql /@CDB1_SYS AS SYSDBA # ✅下一篇: sqlnet.ora (适用于OCI客户端/终端):
WALLET_LOCATION =
(SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /home/oracle/wallet)))
SQLNET.WALLET_OVERRIDE = TRUE
SSL_CLIENT_AUTHENTICATION = FALSE⭐ 步骤7:SQLcl JCEKS——VSCode MCP的配置(关键步骤)
这是该项目的转折点。 它取代了VSCode环境的钱包。密码是用机器绑定的AES密钥加密的——LLM永远不会看到它。
# Launch SQLcl in offline mode
sql /nolog-- Save CDB1 connection to the internal JCEKS vault
SQL> connect -save ai-cdb1 c##mcp_ai/StrongPasswordForAI_2026#@CDB1
-- Name: ai-cdb1
-- User: c##mcp_ai ← NOT empty! ✅
-- Connected ✅ — password encrypted in JCEKS
SQL> connect -save ai-cdb2 c##mcp_ai/StrongPasswordForAI_2026#@CDB2
-- Name: ai-cdb2
-- User: c##mcp_ai ✅
SQL> disconnect
SQL> exit验证:
# List saved connections
sql -l
# NAME CONNECT STRING USER
# ai-cdb1 CDB1 c##mcp_ai
# ai-cdb2 CDB2 c##mcp_ai
# Test connection without password (verification only)
echo "SELECT user, sys_context('USERENV','CON_NAME') con FROM dual;" \
| sql -s ai-cdb1
# C##MCP_AI CDB1$ROOT ✅步骤8:热重定位的额外权限(SYSDBA)
为什么? 热重定位通过DB-Link读取源服务器的在线重做日志。Oracle严格要求SYSDBA或SYSOPER在源端。代理人通过以下方式对此进行了诊断ORA-17628 → ORA-01031.
-- Execute on CDB1 as SYS:
GRANT CREATE PLUGGABLE DATABASE TO c##mcp_ai CONTAINER=ALL;
GRANT CDB_DBA TO c##mcp_ai CONTAINER=ALL;
GRANT SYSDBA TO c##mcp_ai CONTAINER=ALL;步骤9:VSCode中的MCP配置
包装脚本 (scripts/mcp/mcp_sqlcl_wrapper.sh):
#!/bin/bash
# ==============================================================================
# Script name: mcp_sqlcl_wrapper.sh
# Author: KCB Kris
# Description:
# [PL] Wrapper SQLcl dla MCP. Izoluje środowisko od login.sql i gwarantuje
# poprawne zmienne środowiskowe dla procesu działającego w tle VSCode.
# Przekazuje nazwę zapisanego połączenia JCEKS do SQLcl jako serwer MCP.
# [EN] SQLcl wrapper for MCP. Isolates environment from login.sql and ensures
# correct environment variables for VSCode background process.
# Passes saved JCEKS connection name to SQLcl as MCP server.
# ==============================================================================
# VSCode Extension Host does not inherit .bashrc — clear potential conflicts
unset SQLPATH
unset ORACLE_PATH
# Hard environment initialization
export ORACLE_HOME=/u01/app/oracle/product/26.0.0/dbhome_1
export TNS_ADMIN=$ORACLE_HOME/network/admin
export PATH=$ORACLE_HOME/bin:$PATH
# UTF-8 prevents AI hallucinations on special characters
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
# Launch SQLcl with argument = saved JCEKS connection name
# Example call: mcp_sqlcl_wrapper.sh -mcp ai-cdb1
exec $ORACLE_HOME/bin/sql "$@"VSCode配置 (config/mcp/vscode-mcp-config.json):
{
"mcpServers": {
"oracle-dba-cdb1": {
"command": "/home/oracle/scripts/mcp/mcp_sqlcl_wrapper.sh",
"args": ["-mcp", "ai-cdb1"],
"env": {
"ORACLE_HOME": "/u01/app/oracle/product/26.0.0/dbhome_1",
"TNS_ADMIN": "/u01/app/oracle/product/26.0.0/dbhome_1/network/admin",
"NLS_LANG": "AMERICAN_AMERICA.AL32UTF8"
}
},
"oracle-dba-cdb2": {
"command": "/home/oracle/scripts/mcp/mcp_sqlcl_wrapper.sh",
"args": ["-mcp", "ai-cdb2"],
"env": {
"ORACLE_HOME": "/u01/app/oracle/product/26.0.0/dbhome_1",
"TNS_ADMIN": "/u01/app/oracle/product/26.0.0/dbhome_1/network/admin",
"NLS_LANG": "AMERICAN_AMERICA.AL32UTF8"
}
}
}
}钥匙与钱包的区别:论点"ai-cdb1"(JCEKS名称)而不是"/@CDB1"(钱包别名,失败)。SQLcl通过JCEKS在内部解析凭据。
______________________________________________________________________
🚀 热迁移——实际迁移演练
用户提示
You are my experienced Oracle DBA.
The connections "ai-cdb1" and "ai-cdb2" work great and give you powerful
privileges for container management (CDB_DBA).
Your task is to relocate the HR_PDB database from the CDB1 instance to CDB2
with zero downtime (Hot Relocate).
Prepare a plan and provide all commands. Explain how the live relocation
mechanism works in Oracle 23ai/26ai.执行顺序中的实际命令
步骤1:连接到目标数据库(PULL——只有CDB2启动)
CONNECT ai-cdb2
-- JCEKS decrypts the password natively, JDBC connects to CDB2 ✅步骤2:验证来源
-- (via ai-cdb1)
SELECT con_id, name, open_mode FROM v$pdbs WHERE name='HR_PDB';
-- HR_PDB | READ WRITE ✅步骤3:从CDB2到CDB1的数据库链接
CREATE DATABASE LINK cdb1_link
CONNECT TO c##mcp_ai IDENTIFIED BY "passwd"
USING 'CDB1';
-- Database link created ✅步骤4:测试链接
SELECT * FROM dual@cdb1_link;
-- X ✅ — link works, basic privileges OK步骤5:尝试#1——语法错误(AI自己修复了它)
-- ❌ AI tried advanced options
CREATE PLUGGABLE DATABASE hr_pdb
FROM hr_pdb@cdb1_link
RELOCATE AVAILABILITY MAX PARALLEL 4 WITH SERVICES;
-- ORA-00922: missing or invalid option
-- 🔄 AI analyzes the error, removes unsupported clauses, retries ↓步骤6:尝试#2——重做权限不足(AI自己诊断)
-- ❌ Correct syntax, but c##mcp_ai on CDB1 lacks SYSDBA
CREATE PLUGGABLE DATABASE hr_pdb
FROM hr_pdb@cdb1_link
RELOCATE AVAILABILITY MAX;
-- ORA-17628: Oracle error 1031 returned by remote Oracle server
-- ORA-01031: insufficient privileges
-- 🔄 AI: "Hot Relocate must read Online Redo Logs over the network
-- → SYSDBA or SYSOPER required on CDB1.
-- Please grant: GRANT SYSDBA TO c##mcp_ai CONTAINER=ALL"
-- → DBA granted privileges on CDB1 ↓步骤7:✅ 热门搬迁--成功
CREATE PLUGGABLE DATABASE hr_pdb
FROM hr_pdb@cdb1_link
RELOCATE AVAILABILITY MAX;
-- Pluggable database created ✅
-- (HR_PDB on CDB1 AUTOMATICALLY removed by Oracle engine)步骤8:打开并验证
ALTER PLUGGABLE DATABASE hr_pdb OPEN;
ALTER SESSION SET CONTAINER=HR_PDB;
SELECT name, open_mode FROM v$database;
-- HR_PDB | READ WRITE ✅
SELECT name FROM v$services;
-- hr_pdb ✅Oracle 23ai/26ai中热重定位(最大可用性)的工作原理
热迁移是CDB之间的实时PDB迁移 零应用程序停机时间:
- 初始化(PULL) --CDB2通过DB链路向CDB1发起操作
- 背景文件副本 --HR_PDB在CDB2中注册的数据文件
READ WRITECDB1 - 恢复同步(
AVAILABILITY MAX) --CDB2通过DB-Link持续应用CDB1在线重做日志中的更改。这需要SYSDBA/SYSOPER关于来源 - 最终切换 --最小窗口(秒)——服务和会话切换到CDB2
- 自动清理 --CDB1 自动地 确认成功后删除旧PDB。手册
DROP将是一个错误(数据库已不存在)
______________________________________________________________________
🧠 人工智能自愈——DBA分析
通过经验丰富的Oracle DBA的视角评估代理行为:
✅ 特工做得很出色
1.语法自校正(ORA-00922)
Copilot首先试图“过度设计”这些选项(PARALLEL 4 WITH SERVICES),从数据库中收到语法错误,请读取它,以及 自行修复了代码它没有停止工作或寻求帮助。
2.对 AVAILABILITY MAX 条款
代理使用了此高级选项 没有任何提示 来自DBA。 AVAILABILITY MAX 是一个真正的Oracle条款(自12.2起,在26ai中继续),指示引擎在整个重新定位过程中保持源数据库的可用性。这不是幻觉,这是正确的研究。它在这里做得很好。
3.远程权限诊断(ORA-17628→ ORA-01031)
当操作在远程服务器上出错时,代理正确推断:
- DB-Link正常工作(测试双重通过的SELECT)
- 错误来源于CDB1(远程服务器返回的Oracle错误)
- 热重定位通过网络读取在线重做日志→ 这需要
SYSDBA/SYSOPER - 标准
CDB_DBA这里还不够
为什么它如此珍贵? 标准PDB克隆(冷克隆)适用于 CREATE PLUGGABLE DATABASE.Hot重定位(网络上的实时重做流) 严格要求 SYSDBA 或 SYSOPER人工智能在没有被告知的情况下理解了这一点——这是对Oracle机制的深刻理解。
4.死后透明度
代理人在最终报告中记录了自己的错误。对于安全审计来说,这是非常有价值的——决策过程的整个演变过程是显而易见的。
5.对JCEKS架构的认识
在报告和美人鱼图中,代理人明确指出: *“SQLcl中的密码已加密存储”*它知道它是在一个安全的环境中运行的——从JCEKS提取的凭据,它自己看不到。
⚠️ 代理错误(DBA更正之前)
| 错误 | 描述 | 更正 |
|---|---|---|
| 推送方向 | 初步建议: ALTER PLUGGABLE DATABASE ... RELOCATE TO (不存在) | DBA澄清:Oracle Multitenant=始终对目标进行PULL操作 |
| 缺少前缀 | FROM cdb1_link 而不是 FROM hr_pdb@cdb1_link | Oracle要求 pdb_name@link_name |
| 不必要的DROP | 建议手册 DROP PLUGGABLE DATABASE 在CDB1上 | 成功后,RELOCATE会自动删除源代码 |
这是代理工作流最漂亮的例子 --AI实时独立调试了一个问题。我们见证了人工智能分析Oracle错误,理解加密架构,并请求精确定义的权限。 您已经为数据库生命周期管理构建了一个功能齐全的L5代理。
______________________________________________________________________
🔒 安全
矩阵:Oracle钱包与SQLcl JCEKS
| 特性 | Oracle钱包(cwallet.sso) | SQLcl JCEKS存储 |
|---|---|---|
| 与VSCode MCP配合使用 | ❌ 否(JDBC精简:缺少JVM标志) | ✅ 是(本机JDBC集成) |
| 在码头工作 | ✅ 是(OCI客户端) | ✅ 是的 |
| LLM看到密码 | ❌ 否 | ❌ 没有 |
| 加密 | AES256、Oracle SEPS | AES、JCEKS(Java企业标准) |
| 机器绑定 | 否(便携式钱包) | 是(钥匙绑定到机器) |
| 配置 | mkstore + sqlnet.ora | connect -save --一个命令 |
| 安全级别 | 企业✅ | 企业✅ |
| 推荐 | 终端/CLI | VSCode MCP← 这个项目 |
连接加密验证
@scripts/security/check_connection_encryption.sql
-- Verifies: encryption algorithm, authentication method
-- Native Network Encryption (AES256) enabled by default in Oracle 26ai人工智能运营审计
CREATE AUDIT POLICY ai_mcp_audit
ACTIONS
ALTER PLUGGABLE DATABASE,
CREATE PLUGGABLE DATABASE,
DROP PLUGGABLE DATABASE,
CREATE DATABASE LINK;
AUDIT POLICY ai_mcp_audit BY c##mcp_ai;
-- View AI operation history:
SELECT event_timestamp, action_name, sql_text
FROM unified_audit_trail
WHERE dbusername = 'C##MCP_AI'
ORDER BY event_timestamp DESC;______________________________________________________________________
🐛 故障排除
问题1:ORA-01017之后 connect -save /@CDB1 --空用户/密码
症状: User: (empty), Password: not saved 在SQLcl日志中。
原因: VSCode扩展主机中的JDBC Thin未读取cwallet.sso--丢失 -Doracle.net.wallet_location JVM中的标志(无法从VSCode插件访问)。
解决方案:
-- ❌ Does not work with VSCode MCP (wallet alias):
connect -save ai-cdb1 /@CDB1
-- ✅ Works (explicit credentials → JCEKS):
connect -save ai-cdb1 c##mcp_ai/YourPassword@CDB1问题2:ORA-17628/ORA-01031搬迁期间
原因: 热重定位通过网络读取在线重做日志→ 需要 SYSDBA/SYSOPER.
解决方案:
-- On CDB1 as SYS:
GRANT SYSDBA TO c##mcp_ai CONTAINER=ALL;问题3:ORA-00922 CREATE PLUGGABLE DATABASE ... RELOCATE
原因: 26ai中的条款组合不受支持。
工作语法:
-- ✅ Verified in Oracle 26ai:
CREATE PLUGGABLE DATABASE hr_pdb
FROM hr_pdb@cdb1_link
RELOCATE AVAILABILITY MAX;
-- ❌ ORA-00922 (too many options at once):
CREATE PLUGGABLE DATABASE hr_pdb
FROM hr_pdb@cdb1_link
RELOCATE AVAILABILITY MAX PARALLEL 4 WITH SERVICES;问题4: FROM cdb1_link 而不是 FROM hr_pdb@cdb1_link
原因: Oracle严格要求 pdb_name@link_name 在RELOCATE语法中。
-- ❌ Error:
CREATE PLUGGABLE DATABASE hr_pdb FROM cdb1_link RELOCATE ...
-- ✅ Correct:
CREATE PLUGGABLE DATABASE hr_pdb FROM hr_pdb@cdb1_link RELOCATE ...问题5:成功RELOCATE后手动DROP抛出错误
原因: 成功后,RELOCATE会自动从源中删除PDB。手册 DROP 瞄准一个不再存在的对象。
-- ❌ Unnecessary step (Agent suggested it, DBA corrected it):
DROP PLUGGABLE DATABASE hr_pdb KEEP DATAFILES; -- ORA-65011
-- ✅ After successful RELOCATE — CDB1 no longer has HR_PDB:
SELECT name FROM v$pdbs WHERE name='HR_PDB'; -- No rows selected ✅______________________________________________________________________
🗂️ 存储库结构
oracle-ai-mcp-migration/
│
├── README.md ← This file
├── .gitignore ← Protects wallet, passwords, *.dbf files
│
├── scripts/
│ ├── installation/
│ │ ├── create_cdb_26ai_v3.sh ← CDB1+HR_PDB and CDB2 (v3 — correct)
│ │ ├── setup_network_26ai.sh ← Listener + TNS (listener.ora, tnsnames.ora)
│ │ └── cleanup_failed_dbca.sh ← Cleanup after failed installation
│ │
│ ├── security/
│ │ ├── AI_PDB_Migration_Role.sql ← c##mcp_ai (FINAL version)
│ │ └── check_connection_encryption.sql ← AES256 verification
│ │
│ ├── database/
│ │ └── enable_archivelog_mode.sql ← ARCHIVELOG for CDB1 and CDB2
│ │
│ └── mcp/
│ └── mcp_sqlcl_wrapper.sh ← SQLcl Wrapper (JCEKS, env isolation)
│
├── config/
│ ├── db_home_fs_26ai.rsp ← Installation response file
│ ├── grid_restart_26ai.rsp
│ ├── db_home_asm_26ai.rsp
│ └── sqlnet.ora.template ← WALLET_LOCATION (for OCI/terminal)
│
└── docs/
├── security.md
└── troubleshooting.md______________________________________________________________________
❓ 常见问题解答
Q: 为什么Oracle钱包不能与VSCode一起使用?
VSCode扩展主机通过JDBC精简驱动程序运行SQLcl,不带JVM标志 -Doracle.net.wallet_location没有它,JDBC会发送一个空用户。终端使用OCI客户端(C库),它读取 sqlnet.ora 本地。这是一个根本的架构差异——不是bug,也不是配置错误。
Q: SQLcl JCEKS和Oracle钱包一样安全吗?
是的,对于这个用例。两者都加密密码(JCEKS:AES,机器绑定),并且都防止LLM读取密码。这两种机制都实现了安全目标。
Q: 为什么热重定位而不拔/插?
Hot Relocate提供零停机时间。HR_PDB仍然存在 READ WRITE 在整个操作过程中。需要拔下/插入 CLOSE IMMEDIATE --应用程序在操作期间不可用。
Q: 是否始终需要SYSDBA?
号码 SYSDBA 是必需的 仅 用于热重定位(通过网络读取重做日志)。对于拔出/插入, CREATE PLUGGABLE DATABASE + CDB_DBA 足够了。
Q: DB链接必须使用c#mcp_ai吗?
是的——根据最小特权和安全原则。使用 SYS 在生产中通过DB-Link是不可接受的。
______________________________________________________________________
📜 免责声明
这是一个演示解决方案(PoC)。在生产环境中,添加: Human-in-the-loop 之前 RELOCATE,最低权限限制、审核和监控。始终在生产前进行测试。
______________________________________________________________________
Built by a practicing DBA — mistakes, pivots, and successes included. Because that's what real engineering looks like.
