pylibseekdb
Low-level Python bindings for the seekdb C client library.
🚀 What is OceanBase seekdb?
OceanBase seekdb is an AI-native search database that unifies relational, vector, full-text, JSON, and GIS in a single engine, enabling hybrid search and in-database AI workflows.
📖 Read the launch blog → · 📚 Docs →
✨ Why seekdb for Agents?
🔥 Streaming Write + Concurrent Search, Without the P99 Spike
Agent workloads are continuous write + millisecond-later read. seekdb's async index pipeline (Change Stream) decouples DML from index build, and its two-level HNSW (incremental + snapshot) makes newly-written vectors immediately searchable.
The write path commits and returns without waiting on index construction. The Change Stream pipeline consumes the redo log asynchronously and updates the delta HNSW. Queries hit both delta and snapshot indexes with fine-grained read locks — this is why P99 stays flat under concurrency.
🌿 Copy-on-Write Sandboxes for Agent Exploration
FORK DATABASE snapshots an entire database in seconds — no data copy. Agents experiment freely (write, query, even break tables); then MERGE TABLE commits the work back, or DROP DATABASE discards it.
🔍 Hybrid Search in a Single SQL
Vector + full-text + scalar filter pushed into one execution plan. No N+1 client-side merging, no glue code to combine results.
🐬 MySQL-Compatible, ACID, Embeddable
Built on the proven OceanBase SQL engine. Works as an embedded library, a single-node server, or in the OceanBase distributed cluster. Full ACID, real-time writes, and the entire MySQL ecosystem out of the box.
Installation
pip install pylibseekdb
Logical version migration
pylibseekdb installs seekdb-dump and seekdb-restore for migrating an
embedded database without opening an old data directory with a new runtime.
Stop all application writes and DDL, then create the dump while the old wheel
is still installed:
seekdb-dump ./old.db -o backup.sql
After installing the new wheel, restore into a new or otherwise empty instance:
seekdb-restore ./new.db backup.sql
The dump is mysql-compatible SQL, so stdout, stdin, and external compression can be used:
seekdb-dump ./old.db | gzip > backup.sql.gz
gzip -dc backup.sql.gz | seekdb-restore ./new.db
By default all user databases are included. Repeat --database NAME to select
specific databases. System databases, users, and grants are never exported.
Tables, their data and indexes, and ordinary views are supported. Triggers,
stored routines, events, materialized views, and unknown object types are
reported before any SQL is written and make the command fail. To deliberately
create a partial dump, use --ignore-unsupported. Restore warns with the
skipped-object list and continues without those objects.
seekdb-restore refuses a target containing any user table or view. A failed
restore can contain already-applied DDL, so discard that target and retry with
an empty instance.
Requirements
- CPython >= 3.11
- Linux x86_64 or aarch64 with glibc >= 2.28 (Alpine / musl not supported yet)
- macOS arm64 >= 15.6
🎬 Quick Start
pylibseekdb exposes a lightweight DB-API 2-style interface directly over the seekdb C driver.
It currently starts a local seekdb runtime via open(). Native embedded-mode support will be released soon.
import pylibseekdb as seekdb
# Start a local seekdb runtime (embedded-mode support will be released soon)
seekdb.open(db_dir="./seekdb.db")
# Get a connection and a cursor
conn = seekdb.connect(database="test", autocommit=True)
cursor = conn.cursor()
# Create a table with a vector column and an HNSW index
cursor.execute("""
CREATE TABLE IF NOT EXISTS articles (
id INT PRIMARY KEY,
title TEXT,
embedding VECTOR(4),
VECTOR INDEX idx_vec (embedding)
WITH (DISTANCE=l2, TYPE=hnsw, LIB=vsag)
) ORGANIZATION = HEAP
""")
# Insert a row
cursor.execute(
"INSERT INTO articles VALUES (1, 'Hello seekdb', '[0.1, 0.2, 0.3, 0.4]')"
)
# Hybrid / vector search
cursor.execute("""
SELECT id, title,
l2_distance(embedding, '[0.1, 0.2, 0.3, 0.4]') AS dist
FROM articles
ORDER BY dist APPROXIMATE
LIMIT 5
""")
rows = cursor.fetchall()
for row in rows:
print(row)
cursor.close()
conn.close()
seekdb.close()
Multiple instances
One process can manage multiple local seekdb runtimes through the
SeekdbInstance objects returned by open():
import pylibseekdb as seekdb
first = seekdb.open("./first.db")
second = seekdb.open("./second.db")
first_connection = first.connect(database="test")
second_connection = second.connect(database="test")
first_connection.close()
second_connection.close()
first.close()
second.close()
Each instance stores its local socket inside the normalized database directory.
On macOS and Linux, pylibseekdb connects through a per-instance short alias under
/tmp/pylibseekdb-uds-<pid>-XXXXXX, so long database paths do not exceed the
Unix socket pathname limit. The first successful open() also becomes the
module's default instance, preserving the legacy
seekdb.connect(), seekdb.connection_options(), and seekdb.close() API.
Later calls return independent instance objects without changing that default.
Use the object methods for additional instances.
Connect with PyMySQL
connection_options() returns endpoint and authentication arguments shared by
Python MySQL-protocol drivers. PyMySQL is installed with pylibseekdb:
pip install pylibseekdb
import pymysql
import pylibseekdb as seekdb
instance = seekdb.open(db_dir="./seekdb.db")
options = instance.connection_options()
connection = pymysql.connect(database="test", **options)
try:
with connection.cursor() as cursor:
cursor.execute("SELECT 1")
print(cursor.fetchone())
finally:
# External connections must release the server before its lifecycle handle.
connection.close()
instance.close()
On Unix, options contains only user="root" and unix_socket. For TCP it
contains only user="root" and port; the driver supplies its default local
host. The database name remains caller-owned because PyMySQL uses database
while aiomysql uses db. Treat the returned dictionary as lifecycle-scoped:
the Unix socket alias is removed with the underlying lifecycle handle, so do
not use it after closing its SeekdbInstance and any retained native
connections.
Async initialization and aiomysql
Install aiomysql separately:
pip install aiomysql
import asyncio
import aiomysql
import pylibseekdb as seekdb
async def main():
instance = await seekdb.aopen(db_dir="./seekdb.db")
options = instance.connection_options()
pool = await aiomysql.create_pool(
db="test",
minsize=1,
maxsize=5,
**options,
)
try:
async with pool.acquire() as connection:
async with connection.cursor() as cursor:
await cursor.execute("SELECT 1")
print(await cursor.fetchone())
finally:
pool.close()
await pool.wait_closed()
instance.close()
asyncio.run(main())
aopen() runs the synchronous C startup operation in a worker thread and
returns a SeekdbInstance, so it does not block the asyncio event loop.
Cancelling the coroutine cannot stop seekdb_open() after that worker starts.
Transaction support
conn = seekdb.connect(database="test", autocommit=False)
cursor = conn.cursor()
try:
conn.begin()
cursor.execute("INSERT INTO articles VALUES (2, 'Second', '[0.5,0.6,0.7,0.8]')")
conn.commit()
except seekdb.SeekdbError:
conn.rollback()
raise
finally:
cursor.close()
conn.close()
SQL — Hybrid Search
-- Create table with vector column, full-text index, and HNSW vector index
CREATE TABLE docs (
id INT PRIMARY KEY,
title TEXT,
content TEXT,
embedding VECTOR(384),
FULLTEXT INDEX idx_fts (content) WITH PARSER ik,
VECTOR INDEX idx_vec (embedding)
WITH (DISTANCE=l2, TYPE=hnsw, LIB=vsag)
) ORGANIZATION = HEAP;
-- Hybrid search: vector similarity + full-text match in one query
SELECT id, title,
l2_distance(embedding, '[0.12, 0.34, ...]') AS dist
FROM docs
WHERE MATCH(content) AGAINST('quarterly report')
ORDER BY dist APPROXIMATE
LIMIT 10;
API Reference
Module-level functions
| Function | Description |
|---|---|
open(db_dir="./seekdb.db") |
Start a local runtime and return its SeekdbInstance. The first open instance becomes the module default. |
await aopen(db_dir="./seekdb.db") |
Run open() in a worker thread and return its SeekdbInstance. |
connection_options() |
Return connection arguments for the default instance. The database name is not included. |
connect(database="test", autocommit=False) |
Return a Connection to the default instance. |
close() |
Close and clear the default instance. Idempotent. |
SeekdbInstance
| Attribute or method | Description |
|---|---|
db_dir |
Normalized absolute database directory used by this instance. |
closed |
Whether this instance has been closed. |
connect(database="test", autocommit=False) |
Return a Connection to this instance. |
connection_options() |
Return connection arguments for PyMySQL or aiomysql. |
close() |
Release this instance. Existing native Connection objects keep the underlying lifecycle handle alive until they close. |
Connection
| Method | Description |
|---|---|
cursor() |
Return a new Cursor. |
begin() |
Begin a transaction. |
commit() |
Commit the current transaction. |
rollback() |
Roll back the current transaction. |
close() |
Disconnect and release resources. |
Cursor
| Method | Description |
|---|---|
execute(sql) |
Execute sql; returns the number of rows in the result set (0 for statements without a result set). |
fetchone() |
Return the next row as a tuple, or None. |
fetchall() |
Return all remaining rows as a list of tuple. |
close() |
Free the result set. |
SeekdbError
Exception raised on driver errors. Subclass of RuntimeError.
📚 Use Cases
- 🤖 Agentic AI — streaming memory writes, millisecond-later vector retrieval,
FORK DATABASEfor safe exploration - 📖 RAG & Knowledge Retrieval — hybrid search across enterprise knowledge bases
- 🔍 Semantic Search — embedding-based search for text, images, and other modalities
- 💻 AI-Assisted Coding — semantic code search with multi-project isolation
- 📱 On-Device & Edge AI — lightweight local deployments today, with embedded-mode support coming soon
🌐 Resources
License
Apache-2.0 — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pylibseekdb-1.4.0-cp312-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: pylibseekdb-1.4.0-cp312-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 54.0 MB
- Tags: CPython 3.12+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d32d6f0d3b92b0c719b6c4230a24748ce10666f67052c696359e69138d8fbe7
|
|
| MD5 |
80e40d21fee10221bdce0728cc1a4fc1
|
|
| BLAKE2b-256 |
5cf3452485e45676a7d738720a7a3f7abbf4d24a3d272cbacabef41ae8b8e52c
|
File details
Details for the file pylibseekdb-1.4.0-cp312-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: pylibseekdb-1.4.0-cp312-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 49.4 MB
- Tags: CPython 3.12+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f606579904a19bcd7ec96bc117251db9d4202485fc7355f2a289804d1b3b2c1b
|
|
| MD5 |
0ef44fe951e2c5ca124064b02615c630
|
|
| BLAKE2b-256 |
dfb5ea71acbee58925a51cb1a7137afd2d1c4e3fbb5bf2a0144cd53d299a20df
|
File details
Details for the file pylibseekdb-1.4.0-cp312-abi3-macosx_15_0_x86_64.whl.
File metadata
- Download URL: pylibseekdb-1.4.0-cp312-abi3-macosx_15_0_x86_64.whl
- Upload date:
- Size: 60.5 MB
- Tags: CPython 3.12+, macOS 15.0+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c17f2f75793c287a4f14a51df046e14c32446d35dd64dda9b32c5f41bb9b4b20
|
|
| MD5 |
f07d88f9d57994078faafccf16ccb9dc
|
|
| BLAKE2b-256 |
7785ebd60eac61710da45b447e0ce6b63d124fa944a8c5e84c84f8527e95855b
|
File details
Details for the file pylibseekdb-1.4.0-cp312-abi3-macosx_15_0_arm64.whl.
File metadata
- Download URL: pylibseekdb-1.4.0-cp312-abi3-macosx_15_0_arm64.whl
- Upload date:
- Size: 52.2 MB
- Tags: CPython 3.12+, macOS 15.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2fee55af299f2992dd5d61c9e239ef8855629f4117ee8b4c21dc877160707004
|
|
| MD5 |
05fc119e642a88be2fc7ca8669ecc34d
|
|
| BLAKE2b-256 |
ca034380094699cbd4539971c0b943701f776408c94c28cc3ecdaed7c217bb29
|
File details
Details for the file pylibseekdb-1.4.0-cp311-cp311-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: pylibseekdb-1.4.0-cp311-cp311-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 54.0 MB
- Tags: CPython 3.11, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6aaa3c9e4865d32f533af04eb8eab06d2c10fc581ac38097d618efb44c05dc5b
|
|
| MD5 |
51db850e0c0d45e1cf41148e6216def6
|
|
| BLAKE2b-256 |
71cde54bb304512042cac0514fd607175f5425bd0924330e3eb74937c2afe827
|
File details
Details for the file pylibseekdb-1.4.0-cp311-cp311-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: pylibseekdb-1.4.0-cp311-cp311-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 49.4 MB
- Tags: CPython 3.11, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e37b931417b7fc7fc88d15fd8b9b0dad499cd05e693cc483aa3743840e85f0c0
|
|
| MD5 |
274455872344ff3a7801424ff56e171c
|
|
| BLAKE2b-256 |
6493e9a13b996b5561f89c9a4f1b62796f8a6230a5dce215869e3cfef8adc4f1
|
File details
Details for the file pylibseekdb-1.4.0-cp311-cp311-macosx_15_0_x86_64.whl.
File metadata
- Download URL: pylibseekdb-1.4.0-cp311-cp311-macosx_15_0_x86_64.whl
- Upload date:
- Size: 60.5 MB
- Tags: CPython 3.11, macOS 15.0+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50ea01a5bec94a0642338323c036b83a98c987d5b040e5e9abb9d0d144c2562b
|
|
| MD5 |
4ef6b90fa3d77de58facdd85fcb34b42
|
|
| BLAKE2b-256 |
940931d35ee01a5c996b2b4e62f529ea7f1e2f163b2bf450799aefba8062e3e8
|
File details
Details for the file pylibseekdb-1.4.0-cp311-cp311-macosx_15_0_arm64.whl.
File metadata
- Download URL: pylibseekdb-1.4.0-cp311-cp311-macosx_15_0_arm64.whl
- Upload date:
- Size: 52.2 MB
- Tags: CPython 3.11, macOS 15.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cb2efab9f1321cdb4b034d3a2bd92e41a402fc95e7dc9579c7473a426f96e24
|
|
| MD5 |
76db2dd6ae3e853ad7593775cdc41d6e
|
|
| BLAKE2b-256 |
aea87413d33218aff55a14ec9d20532b49243ffd0579e7a92244922c1885444e
|