[英]Why this BigQuery transaction is not rollbacked?
我正在嘗試利用 BigQuery python API 中的會話來執行多語句事務,就像在這篇博文中顯示的那樣。
這是我的上下文管理器代碼:
from google.cloud import bigquery
class BigquerySession:
"""ContextManager wrapping a bigquerySession."""
def __init__(self, bqclient: bigquery.Client, bqlocation: str = "EU") -> None:
"""Construct instance."""
self._bigquery_client = bqclient
self._location = bqlocation
self._session_id = None
def __enter__(self) -> str:
"""Initiate a Bigquery session and return the session_id."""
job = self._bigquery_client.query(
"SELECT 1;", # a query can't fail
job_config=bigquery.QueryJobConfig(create_session=True),
location=self._location,
)
self._session_id = job.session_info.session_id
job.result() # wait job completion
return self._session_id
def __exit__(self, exc_type, exc_value, traceback):
"""Abort the opened session."""
if exc_type:
print("Transaction failed, performing rollback")
job = self._bigquery_client.query(
"ROLLBACK TRANSACTION;",
job_config=bigquery.QueryJobConfig(
create_session=False,
connection_properties=[
bigquery.query.ConnectionProperty(key="session_id", value=self._session_id)
],
),
location=self._location,
)
job.result()
if self._session_id:
# abort the session in any case to have a clean state at the end
# (sometimes in case of script failure, the table is locked in
# the session)
job = self._bigquery_client.query(
"CALL BQ.ABORT_SESSION();",
job_config=bigquery.QueryJobConfig(
create_session=False,
connection_properties=[
bigquery.query.ConnectionProperty(
key="session_id", value=self._session_id
)
],
),
location=self._location,
)
job.result()
return False
它似乎工作正常,但如果我嘗試中斷事務而不故意提交它,它無論如何都會寫入結果而不回滾,即使顯式執行它也是如此。
這是一個交易的例子:
# Open transaction
job = self.client.query(
"BEGIN TRANSACTION;",
job_config=bigquery.QueryJobConfig(
create_session=False,
connection_properties=[
bigquery.query.ConnectionProperty(key="session_id", value=session_id)
]
),
location=self.dataset.location,
)
job.result()
# DML queries
job = self.client.query(
aggregation_query,
job_config=bigquery.QueryJobConfig(
create_session=False,
connection_properties=[
bigquery.query.ConnectionProperty(key="session_id", value=session_id)
],
destination=f"{self.dataset.project}.{self.dataset.dataset_id}.{table_name}",
create_disposition="CREATE_NEVER",
write_disposition="WRITE_APPEND"
),
location=self.dataset.location,
)
print(job.result())
# This will avoid the commit statement
raise KeyboardInterrupt
# Commit transaction
job = self.client.query(
"COMMIT TRANSACTION;",
job_config=bigquery.QueryJobConfig(
create_session=False,
connection_properties=[
bigquery.query.ConnectionProperty(key="session_id", value=session_id)
],
),
location=self.dataset.location,
)
job.result()
正如我所說,運行此代碼后,回滾語句運行,我也可以在控制台的運行作業中看到它,但是之后我仍然會在目標表中找到寫入的行。
我的假設是 2: 帶有目標語句的 select 不被視為 DML,因此不受回滾操作的影響,或者 session ZDB974238714CA8DE634A7CE1D083A14F 中存在錯誤(無論如何它仍應標記為預覽相關文檔Z)在文檔中。
但是我無法證明其中哪一個是正確的。
我設法通過使用INSERT INTO
語句克服了這個問題,而不是使用 python API 指定目標表。 我猜交易功能不包括 python API 方法。 我不確定這是否是一個錯誤,但我在文檔中找不到有關此主題的任何內容。
我最終決定不使用事務功能,因為事實證明它非常不可靠並且還沒有准備好投入生產。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.