Amazon Aurora MySQL DB クラスターからの Lambda 関数の呼び出し - Amazon Aurora

Amazon Aurora MySQL DB クラスターからの Lambda 関数の呼び出し

Amazon Aurora MySQL 互換エディション DB クラスターから AWS Lambda 関数を呼び出すには、ネイティブ関数 lambda_sync または lambda_async を使用します。Aurora MySQL から Lambda 関数を呼び出すには、Aurora DB クラスターから Lambda にアクセスできる必要があります。Aurora MySQL へのアクセス権の付与の詳細については、Lambda へのアクセスを Aurora に許可する を参照してください。lambda_sync 関数および lambda_async の保存された関数の詳細については、Aurora MySQL ネイティブ関数を使用した Lambda 関数の呼び出し を参照してください。

ストアドプロシージャを使用して、AWS Lambda 関数を呼び出すこともできます。しかし、ストアドプロシージャの使用は非推奨です。以下のいずれかのバージョンの Aurora MySQL を使用している場合は、Aurora MySQL ネイティブ関数を使用することを強くお勧めします。

  • MySQL 5.7 互換クラスターの場合は、Aurora MySQL バージョン 2。

  • MySQL 8.0 互換クラスターは、Aurora MySQL バージョン 3.01 以降。ストアドプロシージャは、Aurora MySQL バージョン 3 では使用できません。

Lambda へのアクセスを Aurora に許可する

Aurora MySQL DB クラスターから Lambda 関数を呼び出すには、まず Lambda へのアクセス権限をクラスターに付与する必要があります。

Lambda へのアクセス権限を Aurora MySQL に付与するには
  1. Aurora MySQL DB クラスターからの Lambda 関数の呼び出しを許可するアクセス許可を付与する AWS Identity and Access Management (IAM) ポリシーを作成します。手順については、「AWS Lambda リソースにアクセスするための IAM ポリシーの作成」を参照してください。

  2. IAM ロールを作成して、「AWS Lambda リソースにアクセスするための IAM ポリシーの作成」で作成した IAM ポリシーを新しい IAM ロールにアタッチします。手順については、「Amazon Aurora が AWS のサービスにアクセスすることを許可する IAM ロールの作成」を参照してください。

  3. DB クラスターの aws_default_lambda_role パラメータに新しい IAM ロールの Amazon リソースネーム (ARN) を設定します。

    クラスターが Aurora Global Database の一部である場合は、グローバルデータベース内の Aurora クラスターごとに同じ設定を適用します。

    DB クラスターのパラメータの詳細については、「Amazon Aurora の DB クラスターパラメータと DB インスタンスパラメータ」を参照してください。

  4. Aurora MySQL DB クラスター内のデータベースユーザーが Lambda 関数を呼び出せるように、「Amazon Aurora が AWS のサービスにアクセスすることを許可する IAM ロールの作成」で作成したロールをその DB クラスターに関連付けます。DB クラスターへの IAM ロールの関連付けの詳細については、「IAM ロールと Amazon Aurora MySQL DB クラスターの関連付け」を参照してください。

    クラスターが Aurora Global Database の一部である場合は、グローバルデータベース内の Aurora クラスターごとにロールを関連付けます。

  5. Lambda へのアウトバウンド接続を許可するように Aurora MySQL DB クラスターを設定します。手順については、「Amazon Aurora MySQL から他の AWS のサービスへのネットワーク通信の有効化」を参照してください。

    クラスターが Aurora Global Database の一部である場合は、グローバルデータベース内の Aurora クラスターごとにアウトバウンド接続を有効にします。

Aurora MySQL ネイティブ関数を使用した Lambda 関数の呼び出し

注記

Aurora MySQL バージョン 2 または Aurora MySQL バージョン 3.01 以降を使用しているときには、ネイティブ関数 lambda_sync および lambda_async を呼び出すことができます。Aurora MySQL のバージョンの詳細については、「Amazon Aurora MySQL のデータベースエンジンの更新」を参照してください。

ネイティブ関数 lambda_sync および lambda_async を呼び出すことで、Aurora MySQL DB クラスターから AWS Lambda 関数を呼び出すことができます。このアプローチは、Aurora MySQL で実行しているデータベースを 他の AWS のサービスと統合するときに便利です。例えば、データベースの特定のテーブルに行が挿入されるたびに Amazon Simple Notification Service (Amazon SNS) を使用して通知を送信するような場合があります。

ネイティブ関数を使用した Lambda 関数の呼び出し

lambda_sync 関数と lambda_async 関数は、Lambda 関数を同期的および非同期に呼び出す組み込みのネイティブ関数です。別のアクションに移る前に、Lambda 関数の結果を知る必要がある場合は、同期関数 lambda_sync を使用します。別のアクションに移る前に、呼び出した Lambda 関数の結果を知る必要がない場合は、非同期関数 lambda_async を使用します。

Aurora MySQL バージョン 3 でのロールの付与

Aurora MySQL バージョン 3 では、ネイティブ関数を呼び出すユーザーは AWS_LAMBDA_ACCESS ロールが付与されている必要があります。ユーザーにこのロールを付与するには、DB インスタンスに管理者ユーザーとして接続し、次のステートメントを実行します。

GRANT AWS_LAMBDA_ACCESS TO user@domain-or-ip-address

次のステートメントを実行することで、このロールを取り消すことができます。

REVOKE AWS_LAMBDA_ACCESS FROM user@domain-or-ip-address
ヒント

Aurora MySQL バージョン 3 でロールテクニックを使用する場合は、SET ROLE role_name または SET ROLE ALL ステートメントを使用してロールを有効化することもできます。MySQL 8.0 ロールシステムに馴染みがない場合は、ロールベースの特権モデル で詳細を確認頂けます。詳細については、「MySQL リファレンスマニュアル」の「ロールの使用」を参照してください。

これは現在アクティブなセッションにのみ適用されます。再接続するときは、もう一度 SET ROLE ステートメントを実行して、権限を付与する必要があります。詳細については、MySQL リファレンスマニュアルの「SET ROLE ステートメント」を参照してください。

ユーザーが DB インスタンスに接続したときに、activate_all_roles_on_login DB クラスターパラメータを使用して、すべてのロールを自動的に有効化できます。このパラメータを設定すると、SET ROLE ステートメントを明示的に呼び出してロールをアクティブ化する必要はありません。詳細については、MySQL リファレンスマニュアルの「activate_all_roles_on_login」を参照してください。

Lambda 関数を呼び出そうとしたときに次のようなエラーが表示される場合は、SET ROLE ステートメントを実行します。

SQL Error [1227] [42000]: Access denied; you need (at least one of) the Invoke Lambda privilege(s) for this operation

Aurora MySQL バージョン 2 での権限の付与

Aurora MySQL バージョン 2 では、ネイティブ関数を呼び出すユーザーには INVOKE LAMBDA 権限が付与されている必要があります。ユーザーにこの権限を付与するには、DB インスタンスに管理者ユーザーとして接続し、次のステートメントを実行します。

GRANT INVOKE LAMBDA ON *.* TO user@domain-or-ip-address

次のステートメントを実行することで、この権限を取り消すことができます。

REVOKE INVOKE LAMBDA ON *.* FROM user@domain-or-ip-address

lambda_sync 関数の構文

lambda_sync 関数を RequestResponse 呼び出しタイプで同期的に呼び出します。関数は、JSON ペイロードで Lambda 呼び出しの結果を返します。関数の構文は次のとおりです。

lambda_sync ( lambda_function_ARN, JSON_payload )

lambda_sync 関数のパラメータ

lambda_sync 関数には以下のパラメータがあります。

lambda_function_ARN

呼び出す Lambda 関数の Amazon リソースネーム (ARN)。

JSON_payload

呼び出した Lambda 関数の JSON 形式の ペイロード

注記

Aurora MySQL バージョン 3 は MySQL 8.0 からの JSON 分析関数をサポートしています。ただし、Aurora MySQL バージョン 2 には、これらの関数は含まれていません。Lambda 関数が、数値や文字列など、アトミック値を返す場合、JSON 分析は必要ありません。

lambda_sync 関数の例

lambda_sync に基づく次のクエリは、関数 ARN を使用して Lambda 関数 BasicTestLambda を同期的に呼び出します。関数のペイロードは {"operation": "ping"} です。

SELECT lambda_sync( 'arn:aws:lambda:us-east-1:123456789012:function:BasicTestLambda', '{"operation": "ping"}');

lambda_async 関数の構文

lambda_async 関数を Event 呼び出しタイプで非同期に呼び出します。関数は、JSON ペイロードで Lambda 呼び出しの結果を返します。関数の構文は次のとおりです。

lambda_async ( lambda_function_ARN, JSON_payload )

lambda_async 関数のパラメータ

lambda_async 関数には以下のパラメータがあります。

lambda_function_ARN

呼び出す Lambda 関数の Amazon リソースネーム (ARN)。

JSON_payload

呼び出した Lambda 関数の JSON 形式の ペイロード

注記

Aurora MySQL バージョン 3 は MySQL 8.0 からの JSON 分析関数をサポートしています。ただし、Aurora MySQL バージョン 2 には、これらの関数は含まれていません。Lambda 関数が、数値や文字列など、アトミック値を返す場合、JSON 分析は必要ありません。

lambda_async 関数の例

lambda_async に基づく次のクエリは、関数 ARN を使用して Lambda 関数 BasicTestLambda を非同期的に呼び出します。関数のペイロードは {"operation": "ping"} です。

SELECT lambda_async( 'arn:aws:lambda:us-east-1:123456789012:function:BasicTestLambda', '{"operation": "ping"}');

トリガーを使用した Lambda 関数の呼び出し

トリガーを使用して、データ変更ステートメントで Lambda を呼び出すことができます。次の例では、lambda_async ネイティブ関数を使用して変数に結果を保存します。

mysql>SET @result=0; mysql>DELIMITER // mysql>CREATE TRIGGER myFirstTrigger AFTER INSERT ON Test_trigger FOR EACH ROW BEGIN SELECT lambda_async( 'arn:aws:lambda:us-east-1:123456789012:function:BasicTestLambda', '{"operation": "ping"}') INTO @result; END; // mysql>DELIMITER ;
注記

トリガーは SQL ステートメントごとに 1 回実行されるのではなく、行ごとに 1 回、一度に 1 行ずつ変更されます。トリガーが実行されると、プロセスは同期されます。data-modifying ステートメントは、トリガーが完了したときにのみ返されます。

書き込みトラフィックが多いテーブルのトリガーから AWS Lambda 関数を呼び出すときは注意してください。INSERTUPDATEDELETE のトリガーは行ごとにアクティブになります。INSERTUPDATE、または DELETE トリガーがあるテーブルの書き込み負荷が高いと、AWS Lambda 関数の大量の呼び出しが発生します。

Aurora MySQL ストアドプロシージャを使用した Lambda 関数の呼び出し (非推奨)

mysql.lambda_async プロシージャを呼び出すことで、Aurora MySQL DB クラスターから AWS Lambda 関数を呼び出すことができます。このアプローチは、Aurora MySQL で実行しているデータベースを 他の AWS のサービスと統合するときに便利です。例えば、データベースの特定のテーブルに行が挿入されるたびに Amazon Simple Notification Service (Amazon SNS) を使用して通知を送信するような場合があります。

Aurora MySQL バージョンに関する考慮事項

Aurora MySQL バージョン 2 から、これらのストアドプロシージャの代わりにネイティブ関数メソッドを使用して Lambda 関数を呼び出すことができます。ネイティブ関数の詳細については、「ネイティブ関数を使用した Lambda 関数の呼び出し」を参照してください。

Aurora MySQL バージョン 2 では、ストアドプロシージャ mysql.lambda_async はサポートされなくなりました。代わりに、ネイティブの Lambda 関数を使用することを強くお勧めします。

Aurora MySQL バージョン 3 では、ストアドプロシージャは使用できません。

mysql.lambda_async プロシージャを使用した Lambda 関数の呼び出し (非推奨)

mysql.lambda_async プロシージャは、Lambda 関数を非同期的に呼び出す組み込みストアドプロシージャです。このプロシージャを使用するには、EXECUTE ストアドプロシージャに対する mysql.lambda_async 権限がデータベースユーザーに必要です。

構文

mysql.lambda_async プロシージャの構文は次のとおりです。

CALL mysql.lambda_async ( lambda_function_ARN, lambda_function_input )

パラメータ

mysql.lambda_async プロシージャには以下のパラメータがあります。

lambda_function_ARN

呼び出す Lambda 関数の Amazon リソースネーム (ARN)。

lambda_function_input

呼び出した Lambda 関数の入力文字列 (JSON 形式)。

ベストプラクティスとして、mysql.lambda_async プロシージャへの呼び出しはストアドプロシージャでラップし、トリガーやクライアントコードなどのさまざまな出典から呼び出せるようにすることをお勧めします。このアプローチにより、インピーダンス不整合の問題を回避し、Lambda 関数を簡単に呼び出せるようになります。

注記

書き込みトラフィックが多いテーブルのトリガーから AWS Lambda 関数を呼び出すときは注意してください。INSERTUPDATEDELETE のトリガーは行ごとにアクティブになります。INSERTUPDATE、または DELETE トリガーがあるテーブルの書き込み負荷が高いと、AWS Lambda 関数の大量の呼び出しが発生します。

mysql.lambda_async プロシージャの呼び出しは非同期ですが、トリガーは同期です。大量のトリガーのアクティベーションを発生させるステートメントは、AWS Lambda 関数の呼び出しが完了するのを待機しませんが、クライアントに制御を返す前にトリガーが完了するのを待ちます。

例: AWS Lambda 関数を呼び出して E メールを送信する

次の例では、データベースコードで呼び出せるストアドプロシージャを作成し、Lambda 関数を使用して E メールを送信します。

AWS Lambda 機能

import boto3 ses = boto3.client('ses') def SES_send_email(event, context): return ses.send_email( Source=event['email_from'], Destination={ 'ToAddresses': [ event['email_to'], ] }, Message={ 'Subject': { 'Data': event['email_subject'] }, 'Body': { 'Text': { 'Data': event['email_body'] } } } )

ストアドプロシージャ

DROP PROCEDURE IF EXISTS SES_send_email; DELIMITER ;; CREATE PROCEDURE SES_send_email(IN email_from VARCHAR(255), IN email_to VARCHAR(255), IN subject VARCHAR(255), IN body TEXT) LANGUAGE SQL BEGIN CALL mysql.lambda_async( 'arn:aws:lambda:us-west-2:123456789012:function:SES_send_email', CONCAT('{"email_to" : "', email_to, '", "email_from" : "', email_from, '", "email_subject" : "', subject, '", "email_body" : "', body, '"}') ); END ;; DELIMITER ;

ストアドプロシージャを呼び出して AWS Lambda 関数を呼び出す

mysql> call SES_send_email('example_from@amazon.com', 'example_to@amazon.com', 'Email subject', 'Email content');
例: AWS Lambda 関数を呼び出してトリガーからイベントを発行する

次の例では、Amazon SNS を使用してイベントを発行するストアドプロシージャを作成 します。コードでは、行がテーブルに追加されると、トリガーからプロシージャを呼び出します。

AWS Lambda 機能

import boto3 sns = boto3.client('sns') def SNS_publish_message(event, context): return sns.publish( TopicArn='arn:aws:sns:us-west-2:123456789012:Sample_Topic', Message=event['message'], Subject=event['subject'], MessageStructure='string' )

ストアドプロシージャ

DROP PROCEDURE IF EXISTS SNS_Publish_Message; DELIMITER ;; CREATE PROCEDURE SNS_Publish_Message (IN subject VARCHAR(255), IN message TEXT) LANGUAGE SQL BEGIN CALL mysql.lambda_async('arn:aws:lambda:us-west-2:123456789012:function:SNS_publish_message', CONCAT('{ "subject" : "', subject, '", "message" : "', message, '" }') ); END ;; DELIMITER ;

テーブル

CREATE TABLE 'Customer_Feedback' ( 'id' int(11) NOT NULL AUTO_INCREMENT, 'customer_name' varchar(255) NOT NULL, 'customer_feedback' varchar(1024) NOT NULL, PRIMARY KEY ('id') ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

[Trigger] (トリガー)

DELIMITER ;; CREATE TRIGGER TR_Customer_Feedback_AI AFTER INSERT ON Customer_Feedback FOR EACH ROW BEGIN SELECT CONCAT('New customer feedback from ', NEW.customer_name), NEW.customer_feedback INTO @subject, @feedback; CALL SNS_Publish_Message(@subject, @feedback); END ;; DELIMITER ;

通知をトリガーするには、テーブルに行を挿入します

mysql> insert into Customer_Feedback (customer_name, customer_feedback) VALUES ('Sample Customer', 'Good job guys!');