Aurora DSQLの制約を知ってより理解を深める
「制約を知れば知るほど、もっとそのテクノロジーへの愛が深まる…」
以前こんなツイートしたところ、いくらか反応がありました。
re:Invent 2024におけるAurora DSQLの発表はかなりのインパクトがあったのですが、ドキュメントを見れば見るほど、これは従来のAurora(PostgreSQL)とはかなり違うなぁという印象を持つ人も多いと思います。自分も思いました。
最速のサーバーレス分散SQLデータベース「Aurora DSQL」。トランザクション制御の方式も楽観同時実行制御がベースとなっていたり独特で、かつ通常のPostgreSQLとはコマンドレベルでは、かなり違う(制約がある)部分も見えてきました。
このブログでは、Aurora DSQLの制約(できないこと)を中心に情報をまとめています。まだプレビューのAurora DSQLですが、この制約を知っておくことで、逆にAurora DSQLの使い所や特徴が浮かび上がってきます。
まだ現在はAurora DSQLの利用に料金がかかりません。今のうちにあれこれさわってみつつ、実運用を見据えた時にどのような制約がありそうか体験してみるのも良いと思います。
ほな、いってみよ!!
免責事項
関連資料
Aurora DSQLのアーキテクチャに関する資料
Aurora DSQLがなにでどういった特徴とアーキテクチャをもっているのかを紹介した資料。制約と合わせて改めてこちらを見てもらえれば、理解深まると思います。
- Amazon Aurora DSQL の紹介 | Amazon Web Services ブログ
- Amazon Aurora DSQL の同時実行制御 | Amazon Web Services ブログ
- [新サービス] Aurora が真にサーバーレスでマルチリージョンに対応!リージョンを超えて強い一貫性を持つ Amazon Aurora DSQL が発表されました! | DevelopersIO
- AWS re:Invent 2024 - Deep dive into Amazon Aurora DSQL and its architecture (DAT427-NEW) - YouTube
- [レポート][DAT427-NEW] Amazon Aurora DSQL とそのアーキテクチャを詳しく見る #AWSreInvent | DevelopersIO
Aurora DSQLの制約に関連する情報がまとまっている資料
どんなコマンドがサポート外か、PostgreSQLとの差分は何なのかなどの情報は、基本ユーザーガイドに全てまとまっています。この後、このドキュメントを参考にしながら、できない点を深ぼっていきます。
What is Amazon Aurora DSQL? - Amazon Aurora DSQL
Aurora DSQLで利用できるPostgreSQLプロトコル
以下、サポートされているプロトコルと制約についての記載があるドキュメントです。
Using the PostgreSQL protocol with Aurora DSQL - Amazon Aurora DSQL
独自ロールの作成について
Aurora DSQLはadminという名前のロールを作成します。カスタムデータベースロールを作成する場合は、クラスターへの接続時に認証を行うために、IAMロールと関連付けるためにadminロールを使用する必要があります。詳細はこちらUsing database roles with IAM roles - Amazon Aurora DSQL。
作成できるDatabaseについて
クラスタ内に作成できるデータベースは、postgres
のみ。このデータベースは、最初のクラスター作成時に自動的に作成されます。他のデータベースの作成はできません。この通りエラーになります。
create database hamako;
SQLエラー [0A000]: ERROR: unsupported statement: Createdb
DB接続時のパスワード
長期間有効なパスワードはなく、一時的な認証トークンを利用して接続します。詳細はこちら。
Generating an authentication token in Amazon Aurora DSQL - Amazon Aurora DSQL
冒頭、DeepLによる翻訳。
お好みの SQL クライアントで Amazon Aurora DSQL に接続するには、パスワードとして使用する認証トークンを生成する必要があります。デフォルトでは、AWSコンソールを使用して作成した場合、これらのトークンは自動的に1時間で期限切れになります。AWS CLIまたはSDKを使用してトークンを作成した場合、デフォルトは15分です。最大値は604,800秒、つまり1週間です。クライアントからAurora DSQLに再度接続するには、トークンが期限切れになっていなければ同じトークンを使用できますが、新しいトークンを生成することもできます。
と記載があるとおり、トークンには有効期限があります。実際にアプリケーションで使う場合にどう実装するかは、公式ドキュメントの各ライブラリのサンプルコードを参照してください。
PostgreSQLのデータ型サポート有無
Supported data types in Aurora DSQL - Amazon Aurora DSQL
上記ページに、サポートされているデータ型とAurora DSQL独自のLimitについて記載されています。逆に、上記ページに記載されていないデータ型は基本的に使えないと考えて良さそうです。
私が見かけた範囲でサポート外のものとして代表的なのがSERIAL
データ型,IDENTITY
制約です。例えば、以下のCREATE TABLE
文はエラーとなります。
create table sample_tbl(
choice_no smallint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
quantity int,
number bigint,
price numeric(10,3),
u_id serial,
product_name varchar(10),
product_id char(5),
remarks text,
create_date timestamp(3),
open_date date,
open_time time(3),
delete_flg boolean
);
SQLエラー [42704]: ERROR: type "serial" does not exist
また、IDENTITY
制約も以下の通りエラーとなります。
create table sample_tbl(
choice_no smallint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
);
SQLエラー [0A000]: ERROR: IDENTITY constraint is not supported
主キーの整数型を自動増分で設定したい時にSERIAL
データ型を使う場合も多いと思いますが、そもそもAurora DSQLではサポート外なので要注意です。
またIDENTITY
制約については、以下の記事でやまたつが記載しているような罠もでてくると思うので、運用含めた事前検証は必ずやっておきましょう。
Aurora DSQLにdrizzleでLambdaからmigrationしてみた | DevelopersIO
PostgreSQLの機能でAurora DSQLでは明示的にサポートしていないもの
Unsupported PostgreSQL features in Aurora DSQL - Amazon Aurora DSQL
ここに、Aurora DSQLにおける主要な制約(できないこと)がまとめられています。表形式でまとめてみました。
カテゴリ | 未サポート項目 |
---|---|
Unsupported objects | • Databases - Aurora DSQLは現時点でクラスターあたり1つのデータベースのみをサポート • Views • Temporary Tables • Triggers • Types • Tablespaces • UDFs / Functions(language = SQLの関数以外) • Sequences |
Unsupported constraints | • Foreign keys • Exclusion constraints |
Unsupported operations | • ALTER SYSTEM • TRUNCATE • VACUUM • SAVEPOINT |
Unsupported extensions | Aurora DSQLは現時点でPostgreSQLの拡張機能をサポートしていません。以下の主要な拡張機能は未サポートです: • PL/pgSQL • PostGIS • PGVector • PGAudit • Postgres_FDW • PGCron • pg_stat_statements |
オブジェクトに関しては、先述したpostgres
以外のCREATE DATABASE
、VIEW
,TRIGGER
,TABLESPACE
,SEQUENCE
などがサポート外。それ以外にも、外部キー制約FOREIN KEY
,TRUNCATE
などもサポートしていません。
また、Extensionsも多くがサポート外となっています。
Unsupported SQL Expressionsには、CREATE INDEX(if table has date)
もサポート外であることが記載されています。これもきつい制約ではありますが、テーブルにデータが含まれている時のインデックス作成手段として、CREATE INDEX ASYNC
がAurora DSQL独自でサポートされています(後述)。
データが有るときのCREATE INDEXはサポート外のため、CREATE INDEX ASYNCの利用が必要
Aurora DSQLにおいては、CREATE INDEXはテーブルにデータが無い時だけ実行でき、データが有るときはエラーとなります。以下に簡単な例で見てみます。
CREATE TABLE employees (
id INT PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
department VARCHAR(50),
hire_date DATE,
salary INTEGER
);
INSERT INTO employees (id, first_name, last_name, email, department, hire_date, salary)
VALUES
(1, '山田', '太郎', 'yamada.taro@example.com', '営業部', '2020-04-01', 350000),
(2, '佐藤', '花子', 'sato.hanako@example.com', '人事部', '2021-04-01', 320000),
(3, '鈴木', '一郎', 'suzuki.ichiro@example.com', '技術部', '2019-10-01', 400000),
(4, '田中', '美咲', 'tanaka.misaki@example.com', '営業部', '2022-04-01', 300000);
データが有るときは、CREATE INDEXはエラー
テーブルにデータが含まれているときは、CREATE INDEXは失敗します。
select count(*) from employee;
count|
-----+
4|
CREATE INDEX idx_employees_email ON employees(email);
SQLエラー [0A000]: ERROR: adding an index on a table that already has data is not supported yet
データが無いときは、CREATE INDEXは正常に実行可能
データ削除後であれば、Create Indexは可能。
delete from employees;
select count(*) from employee;
count|
-----+
0|
CREATE INDEX idx_employees_email ON employees(email);
select tablename, indexname from pg_indexes where tablename = 'employees';
tablename|indexname |
---------+-------------------+
employees|employees_pkey |
employees|employees_email_key|
employees|idx_employees_email|
次の検証に入るため、INDEXを削除しておきます。データが有る状態でのDROP INDEXは対応している模様。
drop index idx_employees_email;
データが有るときは、Aurora DSQL固有のCREATE INDEX ASYNCを利用する
CREATE INDEX ASYNC
についての公式マニュアルはこちら。
通常のCREATE INDEX
の後ろにASYNC
を付加するだけで、それ以外は基本的に通常のCREATE INDEX
との大きな違いは無さそうです。
CREATE INDEX ASYNC idx_employees_email ON employees(email);
job_id |
--------------------------+
abedvjhxvnbybm7idq3s7ago3i|
レスポンスに見慣れない、job_id
なるものが返ってきました。これが、Aurora DSQLのCREATE INDEX ASYNC
固有のもので、インデックス作成中にこのジョブの状態を監視することで、ジョブが完了するか失敗するまでセッションをブロックすることができるようです。
以下、マニュアルからの引用。専用のsys.wait_for_job(job_id)
、sys.cancel_job(job_id)
プロシージャが用意されており、それを利用してセッションをブロックすることができる
Aurora DSQL also supports the procedures sys.wait_for_job(job_id) and sys.cancel_job(job_id). sys.wait_for_job lets you block the session until the specified job completes or fails. This procedure returns a Boolean. sys.cancel_job lets you cancel an asynchronous job that is in progress.
試しにwait_for_job
プロシージャを実行すると、以下のレスポンスが返ってきました。既に完了してるってことすね。はい。
CALL sys.wait_for_job('abedvjhxvnbybm7idq3s7ago3i');
Job execution succeeded for job with id abedvjhxvnbybm7idq3s7ago3i
上記のCREATE INDEX ASYNC
を実行後、sys
スキーマ内のjobs
ビューに以下の値が反映されていました。
select * from sys.jobs;
job_id |status |details|
--------------------------+---------+-------+
abedvjhxvnbybm7idq3s7ago3i|completed| |
status
がcompleted
になっているので、既にインデックスの構築が完了していることを表しているようです。もともとテストデータ4件とかですからね。これがもっと大量のテーブルへのインデックス作成であれば、このビューを見ることで、インデックス作成のステータスを確認できるとのことです。
このあたりのDSQL独自のシステムビューについては、以下の公式ドキュメントに記載があるので、併せて参考にしてもらえれば。インデックス作成中であれば、status
はprocessing
と表示されるようです。
トランザクション制御に楽観的同時実行制御を採用
通常リレーショナルデータベースでは採用されない、楽観的同時実行制御が採用されています。対象のユーザーガイドはこちら。
Understanding concurrency control in Aurora DSQL - Amazon Aurora DSQL
なのですが、こちらには、SELECT FOR UPDATE
によるライトスキューの管理などが記載されておらず、そのあたりは、こちらの公式ブログに記載されています。
Amazon Aurora DSQL の同時実行制御 | Amazon Web Services ブログ
通常、ユーザーガイドで情報が不足していることは無いので、このユーザーガイドも現時点ではまだ発展途上なのかもしれません。
DDLとDMLを1トランザクションで実行できない
Aurora DSQLにはプライマリーデータベースノードやリーダーが存在しないため、データベースカタログは分散されており、スキーマの変更は分散トランザクションとして管理されています。そのため、DDLの動作が通常のPosgreSQLとは異なります。
具体的に言うと、DDLとDMLを一つのステートメントで実行しようとすると、エラーとなります。
BEGIN;
CREATE TABLE FOO (ID_col integer);
INSERT into FOO VALUES (1);
SQLエラー [0A000]: ERROR: ddl and dml are not supported in the same transaction
自分が実際ハマった具体例としては、テーブルにサンプルのデータを挿入するクエリ実行時に、CREATE TABLE
後にINSERT
したクエリを実行しようとして上記エラーとなりました。世の中にあるサンプルデータ挿入クエリは概ねそのような構成になっているものが多いと思うので、そのあたりも注意が必要です。
主キーの設定に関して独自の考慮が必要
Primary keys in Aurora DSQL - Amazon Aurora DSQL
Aurora DSQLの内部構造を考慮した主キー戦略が解説されています。冒頭のこの部分をまずは、頭にいれておくのが良いでしょう。
DeepLによる翻訳。
Aurora DSQLでは、テーブルの主キーを定義することは、PostgreSQLのCLUSTER操作や他のデータベースシステムのクラスタ化インデックスに似ています。Aurora DSQLは、すべての列を参照するINCLUDEステートメントを適用し、インデックスで構成されたテーブルを作成します。この構造により、Aurora DSQLの主キーに対するすべての参照は、キーに関連付けられたすべての列の値にアクセスでき、データは常に主キーに従って順序付けられます。CLUSTER操作とは異なり、Aurora DSQLは常にこのインデックスで構成されたテーブルの順序を維持します。
Aurora DSQLは、この主な概念を使用して分散データ管理を構成します。Aurora DSQLは、プライマリキーを使用して、各テーブルまたはインデックスの各行に割り当てられるクラスター全体で一意のキーを構築します。Aurora DSQLは、このキーを使用してストレージを自動的にパーティショニングします。このパーティショニングキーは、Aurora DSQLの自動スケーリングおよび同時実行制御メカニズムにおいて中心的な役割を果たします。
後続の箇条書きに具体的な注意ポイントが記載されています。書き込みが多いテーブルで、単調に増加する整数をプライマリキーとして使用することは避けランダム性をもたせることで、ストレージパーティションを分散させることができるとのことです。
サポートされていないシステムテーブルが多数ある
Using system tables and commands in Aurora DSQL - Amazon Aurora DSQL
Aurora DSQLにおいては、PostgreSQLで利用できるシステムテーブルのうちサポートされていないものが多数あります。
上記公式ドキュメントの後半にシステムカタログテーブルシステムビューのうち、対応の有無が全て記載されているので、参考にしてください。
ロックの状態を確認するpg_locks
なども対象外です。ただ、これらサポート対象外のシステムビューも、SQLを実行するとエラーにはならず、内容が空白になっていることは注意しておきましょう。エラーにならないため、サポートされているのかどうかが逆にわかりにくいと思います。
サポート対象外のシステムビューは、中身が空で返ってくる。
select * from pg_locks;
locktype|database|relation|page|tuple|virtualxid|transactionid|classid|objid|objsubid|virtualtransaction|pid|mode|granted|fastpath|waitstart|
--------+--------+--------+----+-----+----------+-------------+-------+-----+--------+------------------+---+----+-------+--------+---------+
制約を知ることで、よりAurora DSQLへの理解が深まる
以上、公式ドキュメントを紐解きながら、筆者の主観で代表的な制約(PostgreSQLとは違う点)をまとめてみました。Aurora DSQLは、Auroraのブランドが付いていますが、アーキテクチャもトランザクション制御もユースケースも従来のAurora(PostgreSQL)とはかなり異なると言っていいでしょう。
アーキテクチャを知り制約を知ることで、よりユースケースに沿ったAurora DSQLの使い道が見えてくると思います。このブログが何らかの参考になれば幸いです。まだプレビューのAurora DSQL。料金かからないので、今のうちにたんまり触っておきましょう!
それでは、今日はこのへんで。濱田孝治(ハマコー)(@hamako9999)でした。