Cockroach 資料庫
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
- 主鍵欄位實作,使用 CRDB 的UUID
類型,預設會隨機產生 UUID。RowIDField
- 主鍵欄位實作,使用 CRDB 的INT
類型,預設為unique_rowid()
。JSONField
- 與 Postgres 的BinaryJSONField
相同,因為 CRDB 將 JSON 視為 JSONB。ArrayField
- 與 Postgres 擴充功能相同(但不支援多維陣列)。
CRDB 與 Postgres 的線路協定相容,並公開非常相似的 SQL 介面,因此可以使用 PostgresqlDatabase
與 CRDB,雖然不建議這麼做
CRDB 不支援巢狀交易(儲存點),因此在使用
CockroachDatabase
時,已實作atomic()
方法來強制執行此限制。如需更多資訊,請參閱 CRDB 交易。CRDB 在欄位類型、日期函式和內省方面可能與 Postgres 有細微差異。
CRDB 特有的功能由
CockroachDatabase
公開,例如指定交易優先順序或AS OF SYSTEM TIME
子句。
CRDB 交易
CRDB 不支援巢狀交易(儲存點),因此如果遇到無效的巢狀結構,CockroachDatabase
上的 atomic()
方法已被修改為引發例外。如果您希望能夠巢狀使用交易程式碼,可以使用 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])
CockroachDB 實作,基於
PostgresqlDatabase
並使用psycopg2
驅動程式。額外的關鍵字參數會傳遞給 psycopg2 連線建構函式,可用於指定資料庫
user
、port
等。或者,可以在 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
必須接受一個參數,即代表交易正在執行的連線的
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')
- class PooledCockroachDatabase(database[, **kwargs])
CockroachDB 連線集區實作,基於
PooledPostgresqlDatabase
。實作與CockroachDatabase
相同的 API,但會進行客戶端連線集區。
- run_transaction(db, callback[, max_attempts=None[, system_time=None[, priority=None]]])
在具有自動客戶端重試的交易中執行 SQL。有關詳細資訊,請參閱
CockroachDatabase.run_transaction()
。- 參數
db (CockroachDatabase) – 資料庫實例。
callback – 可呼叫的物件,接受單一
db
參數 (其值會與上面傳入的值相同)。
注意
此函數等同於
CockroachDatabase
類別中名稱相同的同名方法。
- class UUIDKeyField
UUID 主鍵欄位,使用 CRDB 的
gen_random_uuid()
函數自動填入初始值。
- class RowIDField
自動遞增的整數主鍵欄位,使用 CRDB 的
unique_rowid()
函數自動填入初始值。
另請參閱
來自 Postgresql 擴充功能的
BinaryJSONField
(可在cockroachdb
擴充模組中取得,並別名為JSONField
)。來自 Postgresql 擴充功能的
ArrayField
。