Cockroach Database

CockroachDB (CRDB) は peewee で十分にサポートされています。

from playhouse.cockroachdb import CockroachDatabase

db = CockroachDatabase('my_app', user='root', host='10.1.0.8')

Cockroach Cloud を使用している場合は、接続文字列を使用して接続パラメータを指定する方が簡単な場合があります。

db = CockroachDatabase('postgresql://root:secret@host:26257/defaultdb...')

注記

CockroachDB には、psycopg2 (postgres) Python ドライバが必要です。

注記

CockroachDB のインストールと入門ガイドはこちらにあります: https://www.cockroachlabs.com/docs/stable/install-cockroachdb.html

SSL 設定

Cockroach クラスタを実行する場合は、SSL 証明書を強くお勧めします。Psycopg2 は SSL をそのままサポートしていますが、データベースを初期化するときに追加のオプションを指定する必要がある場合があります。

db = CockroachDatabase(
    'my_app',
    user='root',
    host='10.1.0.8',
    sslmode='verify-full',  # Verify the cert common-name.
    sslrootcert='/path/to/root.crt')


# Or, alternatively, specified as part of a connection-string:
db = CockroachDatabase('postgresql://root:secret@host:26257/dbname'
                       '?sslmode=verify-full&sslrootcert=/path/to/root.crt'
                       '&options=--cluster=my-cluster-xyz')

クライアント検証の詳細については、libpq ドキュメント を参照してください。

Cockroach 拡張 API

playhouse.cockroachdb 拡張モジュールは、次のクラスとヘルパーを提供します。

  • CockroachDatabase - PostgresqlDatabase のサブクラスで、CRDB での作業用に特別に設計されています。

  • PooledCockroachDatabase - 上記と同様ですが、コネクションプーリングを実装しています。

  • run_transaction() - トランザクション内で関数を 실행하고、クライアント側の自動再試行ロジックを提供します。

CRDB を使用する際に役立つ特殊なフィールドタイプ

  • UUIDKeyField - デフォルトでランダムに生成された UUID を使用して、CRDB の UUID タイプを使用するプライマリキーフィールドの実装です。

  • RowIDField - デフォルトで unique_rowid() を使用して、CRDB の INT タイプを使用するプライマリキーフィールドの実装です。

  • JSONField - CRDB が JSON を JSONB として扱うため、Postgres の BinaryJSONField と同じです。

  • ArrayField - Postgres 拡張と同じですが、多次元配列はサポートしていません。

CRDB は Postgres のワイヤプロトコルと互換性があり、非常に似た SQL インターフェースを公開しているため、PostgresqlDatabase を CRDB で使用することは可能ですが、**お勧めしません**。

  1. CRDB は入れ子になったトランザクション (セーブポイント) をサポートしていないため、atomic() メソッドは、CockroachDatabase を使用している場合にこれを強制するために実装されました。詳細については、CRDB トランザクション を参照してください。

  2. CRDB は、フィールドタイプ、日付関数、イントロスペクションにおいて、Postgres と微妙な違いがある場合があります。

  3. CRDB 固有の機能は、CockroachDatabase によって公開されます。たとえば、トランザクションの優先順位を指定したり、AS OF SYSTEM TIME 句を指定したりすることができます。

CRDB トランザクション

CRDB は入れ子になったトランザクション (セーブポイント) をサポートしていないため、CockroachDatabaseatomic() メソッドは、無効な入れ子が発生した場合に例外を発生させるように変更されました。トランザクションコードを入れ子にできるようにするには、transaction() メソッドを使用します。このメソッドは、最も外側のブロックがトランザクションを管理するようにします (たとえば、入れ子になったブロックを終了しても早期コミットは発生しません)。

@db.transaction()
def create_user(username):
    return User.create(username=username)

def some_other_function():
    with db.transaction() as txn:
        # do some stuff...

        # This function is wrapped in a transaction, but the nested
        # transaction will be ignored and folded into the outer
        # transaction, as we are already in a wrapped-block (via the
        # context manager).
        create_user('some_user@example.com')

        # do other stuff.

    # At this point we have exited the outer-most block and the transaction
    # will be committed.
    return

CRDB は、特別な run_transaction() ヘルパーを使用して利用できる、クライアント側のトランザクション再試行を提供します。このヘルパーメソッドは、再試行が必要になる可能性のあるトランザクションステートメントを実行する役割を持つ呼び出し可能オブジェクトを受け入れます。

run_transaction() の最も簡単な例

def create_user(email):
    # Callable that accepts a single argument (the database instance) and
    # which is responsible for executing the transactional SQL.
    def callback(db_ref):
        return User.create(email=email)

    return db.run_transaction(callback, max_attempts=10)

huey = create_user('huey@example.com')

注記

指定された回数試行してもトランザクションをコミットできない場合は、cockroachdb.ExceededMaxAttempts 例外が発生します。SQL の形式が正しくない場合、制約に違反している場合などは、関数は呼び出し元に例外を発生させます。

あるアカウントから別のアカウントに金額を転送するトランザクションのクライアント側再試行を実装するために run_transaction() を使用した例

from playhouse.cockroachdb import CockroachDatabase

db = CockroachDatabase('my_app')


def transfer_funds(from_id, to_id, amt):
    """
    Returns a 3-tuple of (success?, from balance, to balance). If there are
    not sufficient funds, then the original balances are returned.
    """
    def thunk(db_ref):
        src, dest = (Account
                     .select()
                     .where(Account.id.in_([from_id, to_id])))
        if src.id != from_id:
            src, dest = dest, src  # Swap order.

        # Cannot perform transfer, insufficient funds!
        if src.balance < amt:
            return False, src.balance, dest.balance

        # Update each account, returning the new balance.
        src, = (Account
                .update(balance=Account.balance - amt)
                .where(Account.id == from_id)
                .returning(Account.balance)
                .execute())
        dest, = (Account
                 .update(balance=Account.balance + amt)
                 .where(Account.id == to_id)
                 .returning(Account.balance)
                 .execute())
        return True, src.balance, dest.balance

    # Perform the queries that comprise a logical transaction. In the
    # event the transaction fails due to contention, it will be auto-
    # matically retried (up to 10 times).
    return db.run_transaction(thunk, max_attempts=10)

CRDB API

class CockroachDatabase(database[, **kwargs])

PostgresqlDatabase に基づき、psycopg2 ドライバを使用する CockroachDB 実装です。

追加のキーワード引数は psycopg2 接続コンストラクタに渡され、データベースの userport などを指定するために使用できます。

あるいは、接続の詳細は URL 形式で指定できます。

run_transaction(callback[, max_attempts=None[, system_time=None[, priority=None]]])
パラメータ
  • **callback** - 単一の db パラメータ (このメソッドが呼び出されるデータベースインスタンスになります) を受け入れる呼び出し可能オブジェクトです。

  • **max_attempts** (int) - あきらめる前に試行する最大回数です。

  • **system_time** (datetime) - 指定された値に関して、AS OF SYSTEM TIME としてトランザクションを実行します。

  • **priority** (str) - 「low」、「normal」、または「high」のいずれかです。

戻り値

コールバックによって返された値を返します。

例外

max_attempts を超えた場合は、ExceededMaxAttempts が発生します。

クライアント側の自動再試行を使用して、トランザクションで SQL を実行します。

ユーザー提供の callback

  • **必須** 1 つのパラメータ、トランザクションが実行されている接続を表す db インスタンスを受け入れる必要があります。

  • **必須** コミット、ロールバック、またはその他の方法でトランザクションを管理しようとしないでください。

  • **可能性あり** 複数回呼び出される場合があります。

  • **推奨** 理想的には SQL 操作のみを含める必要があります。

さらに、CRDB は入れ子になったトランザクションをサポートしていないため、この関数が呼び出されるときにデータベースに開いているトランザクションがあってはなりません。そうしようとすると、NotImplementedError が発生します。

最も簡単な例

def create_user(email):
    def callback(db_ref):
        return User.create(email=email)

    return db.run_transaction(callback, max_attempts=10)

user = create_user('huey@example.com')
クラス PooledCockroachDatabase(database[, **kwargs])

PooledPostgresqlDatabaseに基づいた、CockroachDBのコネクションプーリング実装です。CockroachDatabaseと同じAPIを実装していますが、クライアント側でコネクションプーリングを行います。

run_transaction(db, callback[, max_attempts=None[, system_time=None[, priority=None]]])

クライアント側で自動リトライを行うトランザクション内でSQLを実行します。詳細はCockroachDatabase.run_transaction()を参照してください。

パラメータ
  • db (CockroachDatabase) – データベースインスタンス。

  • callback – 単一の`db`パラメータ(上記で渡された値と同じ)を受け入れる呼び出し可能なオブジェクト。

注記

この関数は、CockroachDatabaseクラスの同名のメソッドと同等です。

クラス UUIDKeyField

CRDBの`gen_random_uuid()`関数を使用して初期値を自動的に設定する、UUID主キーフィールドです。

クラス RowIDField

CRDBの`unique_rowid()`関数を使用して初期値を自動的に設定する、自動インクリメント整数主キーフィールドです。

関連項目

  • Postgresql拡張のBinaryJSONField(`cockroachdb`拡張モジュールで利用可能、`JSONField`のエイリアス)。

  • Postgresql拡張のArrayField