【Google Cloud】Cloud Spanner 基本 (トランザクション、ロックの種類)

# 0. はじめに
最近、リレーショナル データベース構造 (Relational) を持ちつつ、水平方向のスケーラビリティ (Horizontal) および 分断耐性 (Partition tolerance) を備えた **NewSQL** という、リレーショナル データベース (RDB) と NoSQL の良い特性を備えたデータベース製品／サービスが商用データベースとして採用されてきています。
Google Cloud では、「**Cloud Spanner**」というマネージドの NewSQL サービスが公開されており、Google Cloud アカウントを持っている場合、すぐに利用することが可能です。
今回は、Cloud Spanner に関する基本的な特徴 (トランザクション、ロック) についてまとめてみようと思います。

※ 分断耐性 (Partition tolerance) : 
CAP定理の定義の一つとなり、システム内のノード間の通信障害が発生しても継続して動作し続けることを意味します。([CAP定理](https://ja.wikipedia.org/wiki/CAP%E5%AE%9A%E7%90%86) )

# 目次
[0. はじめに](#0-はじめに)
[1. Cloud Spannerとは](#1-cloud-spannerとは)
[2. ユースケース](#2-ユースケース)
[3. トランザクションの種類](#3-トランザクションの種類)
　- [3.1 読み書きトランザクション（Read/Write transaction）](#31-読み書きトランザクション)
　- [3.2 読み取り専用トランザクション（Read only transaction）](#32-読み取り専用トランザクション)
　- [3.3 パーティション化された DML (Partitioned DML)](#33-パーティション化された-dml)
[4. ロックの種類](#4-ロックの種類)
　- [4.1 ロックモード](#41-ロックモード)
　- [4.2 ロック互換性](#42-ロック互換性)

# 1. Cloud Spannerとは
Cloud Spanner は、強整合性、水平方向のスケーラビリティ (Horizontal)、分断耐性 (Partition tolerance) および 最大 99.999% の可用性を備えたフルマネージドのデータベース サービスです。 データベースの種類としては「NewSQL」という分類になり、リレーショナル データベース (RDB) と NoSQL の良い特性を備えたサービスとなります。
マルチマスター (マルチライター) であり、複数のリージョン (東京、大阪など) に Cloud Spanner インスタンスを分散させることで、地理的な書き込みトランザクションを分散させることも可能です。
**※ Dual-region 機能を利用する場合は、Cloud Spanner Enterprise Plus エディションを選択する必要があります。 (2024年9月時点)**

# 2. ユースケース
Cloud Spanner を利用するユースケースを簡単に考えてみました。
- 決済システム、ECサイトなど大量の書き込みトランザクションが行われ、かつ、ACID トランザクションを保証する必要があるシステム
- 複数のリージョンにデータベースを分散させ、マルチマスター (マルチライター) による大量の書き込みトランザクションを地理的に分散させる必要があるシステム
- ACID トランザクションを保証しつつ、水平方向のスケーラビリティ (Horizontal) により読み書きトランザクションの性能をリニアに向上させる必要があるシステム

# 3. トランザクションの種類
リレーショナル データベース構造 (Relational) を持ちつつ、水平方向のスケーラビリティ (Horizontal) および 分断耐性 (Partition tolerance) を実現するために、以下のようなトランザクションの種類があります。

## 3.1. 読み書きトランザクション
読み書きトランザクション (Read/Write transaction) は、トランザクションの中で 読み込み (read) と 書き込み (Write) 処理を単一、もしくは、組み合わせて実行するために利用されるトランザクションです。
トランザクション内で読み取りが行われた列(セル)に対して **読み取り共有ロック (ReaderShared)** が獲得され、書き込みが行われた列(セル)に対して **書き込み共有ロック (WriterShared)** が獲得されます。
</br>

## 3.2. 読み取り専用トランザクション
読み取り専用トランザクション（Read only transaction）は、トランザクション内で一貫した読み取り結果が必要な場合に利用されるトランザクションです。
※ Oracle で言えば 読み取り一貫性 機能を実現するためのトランザクションでしょうか。
読み取り専用トランザクション（Read only transaction）の場合、トランザクション内で読み取りが行われた列(セル)に対してロックを獲得しないため、ロックの競合が発生しません。
また、読み取り処理実行時に **タイムスタンプ バウンド (Timestamp bound）** を指定し、読み取り時に指定することができるようです。
</br>
**【タイムスタンプ バウンドの指定】**
- **強力な読み取り (Timestamp bound = 0)**
データベース上の最新状態のデータを取得できる読み取り。
</br>

- **古いデータの読み取り (Timestamp bound > 0)**
データベースに対して最新状態のデータを読み取る必要がない処理の場合、**bounded-staleness** もしくは **exact-staleness** を指定することで、指定した期間内の最新状態のデータを取得できる読み取り。
本設定を利用した読み取り処理はデータの同期を待つ必要がないため、読み取り処理のパフォーマンスを向上できることが期待できます。
</br>

【補足】
**bounded-staleness** : 現在時刻から正確に過去の秒数を指定
**exact-staleness** : 現在時刻から指定した秒数までの過去のうちで最新結果を取得
※ 読み取り専用トランザクション（Read only transaction）の場合に指定できるのは exact-staleness のみ。
※ 単一読み取り処理では、bounded-staleness および exact-staleness を指定可能。
</br>
【参考URL】
[古いデータの読み取り](https://cloud.google.com/spanner/docs/samples/spanner-read-stale-data?hl=ja) 

## 3.3. パーティション化された DML
パーティション化された DML (Partitioned DML) は、DML (UPDATE, DELETE, INSERT) を一括して実行するための仕組みです。 

【補足】
大量データのDML処理の性能を向上させる方法として「**バッチ書き込み**」を利用することができますが、現時点 (2024年9月時点) においては プレビュー機能 となっています。

</br>

【参考URL】
[トランザクションの概要](https://cloud.google.com/spanner/docs/transactions?hl=ja) 
[バッチ書き込みを使用したデータの変更](https://cloud.google.com/spanner/docs/batch-write?hl=ja) ※ プレビュー (2024年9月時点)

# 4. ロックの種類
Cloud Spanner では 4つのロックモード があります。
## 4.1. ロックモード
| ロックモード | 説明 |
|:-:|:--|
|**ReaderShared**|読み書きトランザクション内でテーブルデータの参照が行われた 列 (セル) に対して獲得されるロック。<br> 他のトランザクション内でも同様に該当テーブルデータの参照を行えるようにするために使用。<br>　|
|**WriterShared**|読み書きトランザクション内で DML (UPDATE, DELETE, INSERT) 処理を実施するなど、データの書き込みが行われた場合に変更が行われた 列 (セル) に対して獲得されるロック。<br>　 |
|**Exclusive**| 読み書きトランザクション内で既に ReaderShared ロックを獲得している 列 (セル) に対して変更を実施する場合に獲得される排他的ロック。<br>　 |
|**WriterSharedTimestamp**| 主キーの一部として commit タイムスタンプ があるテーブルに新しい行を挿入する時に獲得される特殊な WriterShared ロック。 |
## 4.2. ロック互換性
各ロックモード間のロック互換性について表で整理してみました。
**「〇」: ロック互換性あり,「✖」: ロック互換性なし, 「-」: N/A (該当なし)**
</br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3540203/eb1e7d2a-6e4f-9905-c4fc-e962ce9196b6.png)






**※ 本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。**
**※ 2024年9月 現在**