簡體   English   中英

為什么這個 BigQuery 事務沒有回滾?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM