Skip to main content

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.

seekdb async index pipeline architecture

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 DATABASE for 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

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pylibseekdb-1.4.0.post1-cp312-abi3-manylinux_2_28_x86_64.whl (54.0 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ x86-64

pylibseekdb-1.4.0.post1-cp312-abi3-manylinux_2_28_aarch64.whl (49.4 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ ARM64

pylibseekdb-1.4.0.post1-cp312-abi3-macosx_15_0_x86_64.whl (58.9 MB view details)

Uploaded CPython 3.12+macOS 15.0+ x86-64

pylibseekdb-1.4.0.post1-cp312-abi3-macosx_15_0_arm64.whl (50.7 MB view details)

Uploaded CPython 3.12+macOS 15.0+ ARM64

pylibseekdb-1.4.0.post1-cp311-cp311-manylinux_2_28_x86_64.whl (54.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

pylibseekdb-1.4.0.post1-cp311-cp311-manylinux_2_28_aarch64.whl (49.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ ARM64

pylibseekdb-1.4.0.post1-cp311-cp311-macosx_15_0_x86_64.whl (58.9 MB view details)

Uploaded CPython 3.11macOS 15.0+ x86-64

pylibseekdb-1.4.0.post1-cp311-cp311-macosx_15_0_arm64.whl (50.7 MB view details)

Uploaded CPython 3.11macOS 15.0+ ARM64

File details

Details for the file pylibseekdb-1.4.0.post1-cp312-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.4.0.post1-cp312-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 58f2544cf7969a9b6cdf4ea1136e0d412443a2e839df656feec1b2712741ef85
MD5 fbae1e97ef59d1543ef491058d4dece8
BLAKE2b-256 8306c39545d88ddec475272991d1c5612f5d5463b843cf29553e5a4ac82ef09e

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.4.0.post1-cp312-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.4.0.post1-cp312-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e2887533ab68a84197a222393e6d8fc8282274aa5e99af4f8259c5dfce147914
MD5 09442254db40e6040728ba6d04f97058
BLAKE2b-256 2fc84125f7926273e5f1217656e9a61715e5b67b8ce42c1e706ae2833b34d6b9

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.4.0.post1-cp312-abi3-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.4.0.post1-cp312-abi3-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 0a0a9a68639547f721f581f184faa793a25e70414e6bed2edf14f379224165d8
MD5 748672a48769536411a43c5ffcb0595c
BLAKE2b-256 c91a3e9e68b8485009153fa0792b0dc1c176a151a4e815759fe7f0dc7b166a2d

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.4.0.post1-cp312-abi3-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.4.0.post1-cp312-abi3-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 ad34939175ee900e0e0af52d32868a50d5470200a34cba32558678b5edb8ed3f
MD5 2a6dd0ec6d791fa78e1da78c0d06af9b
BLAKE2b-256 18842c3c3b540ab23aeb46c14ac337e1cd4401fa5234fa24b0f110944dc93a36

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.4.0.post1-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.4.0.post1-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7c1c1e13148189af1332f69b896a818b674db3a4615c7caf1c9db05055738ad6
MD5 34f7e782afb92c9a6eb392eb09b0a091
BLAKE2b-256 c3ca57b3732abf6a67ee74a6fd117874d8faeded532e3c95c151eaf901ea60cb

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.4.0.post1-cp311-cp311-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.4.0.post1-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 3620c821b1a03a961ccfd76cbcc90f2f05d95bc00e4e0a396cb5ae17eb56f059
MD5 2ef92838de1edc3494e866d69297ba8c
BLAKE2b-256 334f5d9b9a90f9fb3e3f8d765be363b9aaf45c717b934c9b50ddab6beefd1c79

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.4.0.post1-cp311-cp311-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.4.0.post1-cp311-cp311-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 9865c365c69447c0dce32ff22bc33bcc59bc628fc178c430e4e6203f68a429f7
MD5 4115903c928eee2cba1aa8106a57a58b
BLAKE2b-256 f39c7a6864f5338e4ca32185e144460215e92a11ebfedee1404b9fb621502acd

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.4.0.post1-cp311-cp311-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.4.0.post1-cp311-cp311-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 0fab086fc36a638fecbd1e1e2d232e35fa753f1d99072e26b7f0bcbcf2c442ba
MD5 ad0812f073f4f9d88a3db9a535828ab0
BLAKE2b-256 6074477e58bac5f62b1daa66b11c5c05c5e3ea8b313c7343051bec723247122b

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.4.0.post1 This release

8 files

1.4.0

8 files

1.4.0.dev2

1.3.0.post5

8 files

1.3.0.post4

8 files

1.3.0.post3

12 files

1.3.0

18 files

1.2.0

18 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page