MySQL9.0のJavaScriptストアドプログラムについて

目次

はじめに

2024年7月1日にイノベーションリリースとなる MySQL9.0 がリリースされました。

初版となる 9.0.0 は 8,001個以上のテーブルが存在する場合に、再起動ができなくなるというBugが存在した為、削除されています。 MySQL9.0 のご使用を検討されている方は、執筆時点では 2024年7月23日にリリースされた 9.0.1 が最新となりますので、そちらをご使用下さい。

MySQL9.0 の Enterprise Edition では、ストアドプロシージャ及びストアドファンクションを含むストアドプログラムに JavaScript を用いて実装をすることが可能となりました。

※ Community版では使用できません。

これについては、Oracle社のブログでも分かり易く紹介されているので、是非、一読下さい。

また、リファレンスは以下となりますので、使用を検討される方は、こちらもご確認下さい。

ということで、今回は、JavaScriptを用いたストアドプログラムについて確認した内容を執筆したいと思います。

Multilingual Engine Component (MLE)

はじめに、JavaScriptストアドプログラムを実装する為には、Multilingual Engine Component コンポーネントをインストールする必要があります。

コンポーネント自体は、SQL以外の言語をサポートする為のコンポーネントですが、現時点でサポートされているのは、JavaScript のみとなります。

コンポーネントのインストールには INSTALL COMPONENT を使用します。

実装

ストアドファンクション

以下のように簡単な URLエンコード をするファンクションを作成してみました。

1行目は、通常のファンクションと変わりないですが、2行目にある RETURNS句 の型の定義の後に LANGUAGE JAVASCRIPT と定義する必要があります。
また、通常のファンクションを作成する際は、一般的には、以下のリファレンスのように delimiter で区切り文字を変更し、 BEGINEND 内で処理を実装します。

ですが、JavaScriptで実装する際は、AS $$ から $$ 内で処理を実装します。

作成したファンクションを実行すると問題なく実行できています。

ストアドプロシージャ

プロシージャを使用するケースでは、SQLを実行するようなケースが多々ある為、以下のような実装をしてみました。

処理の内容としては、MySQLの Example Databases の world データベースの city テーブルのレコードを同一のテーブル構造を持った blog.city テーブルへコピーするという処理内容となっています。

変数名が長くていけてないのですが、返されるオブジェクトが何なのかを分かりやすくするために命名してみました。

SQLの実行に伴って使用したオブジェクトは以下の通りです。
各メソッドの詳細については、オブジェクト名のリンク先のリファレンスをご参照下さい。

  • SQLを実行するには、最初に Session オブジェクトを使用します。
  • session.sql() の結果は、SqlExecute オブジェクトが返されます。
  • session.prepare() の結果は、PreparedStatement オブジェクトが返されます。
  • SqlExecute.execute() と PreparedStatement.execute() の結果は、SqlResult オブジェクトが返されます。
  • SqlResult.fetchOne() の結果は、Row オブジェクトが返されます。

作成したプロシージャを実行した結果、問題なくレコードがコピーされています。

ちなみに、PreparedStatement.bind() は以下のように world.city テーブルから取得した値を設定していますが、

連想配列を用いたテーブルのカラム名で値を参照することも可能です。

JavaScriptで実装したファンクション&プロシージャの判別方法

ファンクションとプロシージャの一覧を確認したい場合は、 INFORMATION_SCHEMA.ROUTINES で確認することができます。
JavaScriptで実装されたかどうかを判別するには、同テーブルの EXTERNAL_LANGUAGEJAVASCRIPT であるかどうかで確認できます。

MLEコンポーネントのセッション情報とオプション

上記リファレンスに記載されていますが、JavaScriptを用いたストアドプログラムを構成する為の MLE コンポーネントには、以下の関数が用意されています。

  • mle_session_reset()
  • mle_session_state()
  • mle_set_session_state()

中でも非常に便利なのが mle_session_state() で、以下のように JavaScriptの console.log()console.error() に設定した情報を後から確認することができます。

以下のようなプロシージャを作成してみました。
cityテーブルから5件を抽出するクエリですが、取得したデータの Name カラムの値を console.log() で出力し、 Population カラムの値を console.error() で出力してみます。

ひとまず、実行した後に、

mle_session_state('stdout') を参照すると、 console.log() に設定した値が参照できます。

mle_session_state('stderr') も同様に、 console.error() に設定した値が参照できます。

実装過程で、取得した値を確認したい時等、実装中のデバッグ用途として有用に使える手段ではないでしょうか。
よく、Oracleの DBMS_OUTPUT.PUT_LINE のようなものが、MySQLにはないですか?という質問を頂くことがありますが、通常のプロシージャ内では、SELECTクエリで文字列を出力する程度のことしかできません。
しかし、この機能を活用すれば十分に代替になり得そうです。

また、以下のようにJavaScript関数を定義して、出力の際に、システム日時を設定して出力するようにして実装してみます。

これを実行すれば、とある処理にどの位の時間がかかったかが分かるようになります。

現時点で、MySQLではプロシージャの処理に実行時間がかかったとしても スロークエリログ には、プロシージャを呼び出したステートメントが出力されるだけなので、プロシージャ内のどの処理で実行に時間がかかっているかというのは、別途、何らかの手段で確認する必要があります。
その為、このような使い方も非常に有用なデバッグ手段だと思います。

ちなみに、console.log()console.error() で設定した値は蓄積されていくので、1度確認した後は、 SELECT mle_session_reset(); でクリアすることをお勧めします。

制限・制約

ストアドプログラムを JavaScript で実装できるようになったとはいえ、全ての機能が使用できるという訳でもなく、サードパーティのモジュールの使用もサポートされておりません。
詳細については、以下のリファレンスをご確認下さい。

また、JavaScriptストアドプログラムでサポートされているMySQLのデータ型についても、以下のリファレンスに記載がありますので、ご使用の際は、以下のリファレンスもご確認下さい。

ちなみに、MySQL9.0 から導入された VECTOR型 は、まだサポートされていません。

MLEコンポーネントに関するパラメータ

MLEコンポーネントに関するパラメータについては、以下のリファレンスに記載があります。

現時点では、MLEコンポーネントが使用するメモリ量の制限をする mle.memory_max のみとなっており、設定値について上記リファレンスでは、以下のように記載されております。

By default, the amount of memory allocated to the MLE component is 64MB (67108864 bytes). You can adjust this by setting the mle.memory_max system variable up to a maximum of 8GB (8589934592 bytes); the minimum possible value is 32MB.

記載内容からは、次のように読み取れます。

設定値
デフォルト値 64MB
最小値 32MB
最大値 8GB

ですが、こちらのリファレンス では、次のように記載されています。

設定値
デフォルト値 1300MB
最小値 320MB
最大値 64GB

デフォルト値は、以下のようになり、

320M 以下の値を設定した場合は、起動時に以下のようなログが出力されて、設定値は 335544320 となります。

また、64G 以下の値を設定した場合は、起動時に以下のようなログが出力されて、設定値は 68719476736 となりますので、設定値については、後者のリファレンス情報の方が正しいようです。

メモリの使用状況としては、Mle_memory_used で割り当てたメモリの何%が実際に使用されているかを確認でき、メモリ不足でエラーになった際は Mle_oom_errors がカウントされるので、これらのステータス変数を確認しながら、設定値を調整すると良さそうです。

まとめ

Community版では使用できませんが、JavaScript に慣れ親んだ開発者にとっては非常に取っ付きやすく、MySQLのストアドプログラムを実装する敷居が下がるのではないかと思います。
特にデバッグする為の手段が強力になっており、より効率よく実装できることが期待できます。

今回は検証できておりませんが、通常のストアドプログラムとの性能差についても機会があれば確認してみたいと思います。

スマートスタイルTECHブログについて

スマートスタイルTECHブログでは、日頃MySQLのサポート業務に従事している有資格者で構成された技術サポートチームがMySQLに関する技術情報を発信しています。データベースのお困りごとはお気軽にご相談下さい。

よかったらシェアしてね!
  • URLをコピーしました!
目次