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.3.0.post5-cp312-abi3-manylinux_2_28_x86_64.whl (126.1 MB view details)

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

pylibseekdb-1.3.0.post5-cp312-abi3-manylinux_2_28_aarch64.whl (111.3 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ ARM64

pylibseekdb-1.3.0.post5-cp312-abi3-macosx_15_0_x86_64.whl (130.0 MB view details)

Uploaded CPython 3.12+macOS 15.0+ x86-64

pylibseekdb-1.3.0.post5-cp312-abi3-macosx_15_0_arm64.whl (113.4 MB view details)

Uploaded CPython 3.12+macOS 15.0+ ARM64

pylibseekdb-1.3.0.post5-cp311-cp311-manylinux_2_28_x86_64.whl (126.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

pylibseekdb-1.3.0.post5-cp311-cp311-manylinux_2_28_aarch64.whl (111.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ ARM64

pylibseekdb-1.3.0.post5-cp311-cp311-macosx_15_0_x86_64.whl (130.0 MB view details)

Uploaded CPython 3.11macOS 15.0+ x86-64

pylibseekdb-1.3.0.post5-cp311-cp311-macosx_15_0_arm64.whl (113.4 MB view details)

Uploaded CPython 3.11macOS 15.0+ ARM64

File details

Details for the file pylibseekdb-1.3.0.post5-cp312-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post5-cp312-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 38ece65a72fef53ffde1fd90e6d7062bd37fd32a0f57fb08700fd18187b21383
MD5 de6d373bdd737e6d8d125533723e563b
BLAKE2b-256 353db9cae143794de2d9a82b0732acca88a36f733310ef7f8388aa1de91b3c98

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post5-cp312-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post5-cp312-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 15a0a8136f75d0ddf3c6d8fbbc0034cbd9465afe9bbfd836df8818e55e9f3819
MD5 b34a175530dc5a091e6acd1bf61f5345
BLAKE2b-256 8215d67e15173dc91a83645376787c1a1e5f9bede5eea571105d042ff6679721

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post5-cp312-abi3-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post5-cp312-abi3-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 3c98829e80b599e6d0612ceebf27e05ef9a618f94a34f13398ad92f8d2d2d637
MD5 84deaddf9dae14c92a26335c1c5c4db3
BLAKE2b-256 6b3df59782dfe1cc0b55125da89e70a4db919951a6f50449ba829089e2da3a6d

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post5-cp312-abi3-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post5-cp312-abi3-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 64a1c39421e2e330a359ad2925ff55b077fe0159781fa426a098ba22946f4d07
MD5 ef6e352d1f81b2bda2f12482c18d08b7
BLAKE2b-256 5db317562d30ce2dbeb19892413696e6e6072a747b803a08cf83b9e293e289cf

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post5-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post5-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 41a36419f69b8fca27bb9cb67959726a96a70c62ae36b86327e071df45c47701
MD5 fcbb740fa6367f49ca8cc42b0ab14e91
BLAKE2b-256 ae857f38c9ba7435dfdb7445fc9338bec4e56346d1bafb58aa46d6482e2e8e16

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post5-cp311-cp311-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post5-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9b2166b6fcbd2b74872ea1fbd8dfb853f36eba4ba6c5f618cdb968f42bf47697
MD5 c18c0fed16d3b0d1bc2f5bbbacc44e86
BLAKE2b-256 13abe0d5cc6556b66ad75aad45e74f05ed419803d5974485812629bd6a53d7e4

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post5-cp311-cp311-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post5-cp311-cp311-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 b0d147097bfe2928dc2f483f3ca0816f64d27ff5d39274ce411010d5e8299c78
MD5 6cb0cefb0876a1f0c452c8adccd59a41
BLAKE2b-256 9d07dca43a4cedd9fbdb0b1086a8b024568a5ebaa6286cff7b30cf918516d276

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post5-cp311-cp311-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post5-cp311-cp311-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 339bb0137d84f2b06c0436f9674e1aee86a6e59e55477af26fff8aa6a9b18d59
MD5 04c0c797da14962fc56f3f82303d8195
BLAKE2b-256 655a160737bca61aee6dd0b0a2d635b89148528ab08b8a32f33a1c6f91cecf61

See more details on using hashes here.

Release history Release notifications | RSS feed

1.4.0.post1

8 files

1.4.0

8 files

1.4.0.dev2

This release

1.3.0.post5 This release

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