MySQL 9.0 企业版和 MySQL HeatWave 推出了一项令人振奋的创新特性:支持使用 JavaScript 编写存储过程和函数。
这标志着开发者可以凭借对 JavaScript 的熟悉度,以及丰富的 JavaScript 生态资源,更加高效地编写 MySQL 存储过程。不仅极大地提升了开发者的生产力,还大幅降低了存储过程编写的门槛,使得广大开发者能够投身其中。此外,这种设计巧妙地减少了数据库服务器与应用程序之间的数据传输量,优化了整体性能。
准备 MySQL 9 环境
为了深入浅出地展示 JavaScript 存储程序的强大功能,我们将利用 MySQL 企业版 9.2 的 Docker 容器进行环境搭建。
从 Oracle Container Registry(OCR) 拉取 MySQL 企业版 9.2 的镜像。
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@el7 ~]# docker pull container-registry.oracle.com/mysql/enterprise-server:9.2 9.2: Pulling from mysql/enterprise-server 08b26210552c: Pull complete c743ba8e0994: Pull complete 6ed95c0f26d2: Pull complete cae75ca37528: Pull complete 2b352847173b: Pull complete 16a46733c092: Pull complete b6e314a3018d: Pull complete Digest: sha256:5225178395d4920f4675472c4207d10e127690d5704df2103d03bfaea5af992d Status: Downloaded newer image for container-registry.oracle.com/mysql/enterprise-server:9.2 container-registry.oracle.com/mysql/enterprise-server:9.2 [root@el7 ~]#
使用以下命令运行 MySQL 企业版容器:
1 2 3 4 docker run --name=mysql9 \ --restart on-failure \ -e MYSQL_ROOT_PASSWORD=root \ -d container-registry.oracle.com/mysql/enterprise-server:9.2
连接到数据库,并查看版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@el7 ~]# docker exec -it mysql9 mysql -uroot -proot mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 9 Server version: 9.2.0-commercial MySQL Enterprise Server - Commercial Copyright (c) 2000, 2025, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> select version(); +------------------+ | version() | +------------------+ | 9.2.0-commercial | +------------------+ 1 row in set (0.00 sec)
至此,我们已经成功搭建了 MySQL 9 的运行环境。
安装 MLE 组件
MySQL 的多语言引擎(MLE)组件是实现 JavaScript 存储程序的关键所在。MLE 组件赋予存储过程和函数支持 SQL 之外语言的能力,是 MySQL 企业版的专属特性。
使用 MySQL 9.2 中的 MLE 组件,您可以创建和执行用 JavaScript(ECMAScript) 编写的 MySQL 存储程序。
安装 MLE 组件:
1 2 mysql> INSTALL COMPONENT 'file://component_mle'; Query OK, 0 rows affected (0.24 sec)
查看组件状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 mysql> SHOW STATUS LIKE 'mle%'; +------------------------------+---------------+ | Variable_name | Value | +------------------------------+---------------+ | mle_heap_status | Not Allocated | | mle_languages_supported | JavaScript | | mle_memory_used | 0 | | mle_oom_errors | 0 | | mle_session_resets | 0 | | mle_sessions | 0 | | mle_sessions_max | 0 | | mle_status | Inactive | | mle_stored_functions | 0 | | mle_stored_procedures | 0 | | mle_stored_program_bytes_max | 0 | | mle_stored_program_sql_max | 0 | | mle_stored_programs | 0 | | mle_threads | 0 | | mle_threads_max | 1 | +------------------------------+---------------+ 15 rows in set (0.00 sec)
用 JavaScript 编写的存储程序
现在,我们开始编写一个简单的 JavaScript 存储函数。
1 2 3 4 5 6 7 mysql> CREATE FUNCTION add_nos(arg1 INT, arg2 INT) -> RETURNS INT LANGUAGE JAVASCRIPT AS -> $$ $> return arg1 + arg2 $> $$ -> ; ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
但可能会遇到上面的报错。要放宽上述函数创建的条件(用户必须拥有超级特权,并且函数必须声明为确定性的,或者不修改数据),可以将全局的log_bin_trust_function_creators系统变量设置为1。默认情况下,这个变量的值为0,但你可以这样修改它:
1 2 mysql> set global log_bin_trust_function_creators = on; Query OK, 0 rows affected, 1 warning (0.00 sec)
再次执行创建语句,成功。
1 2 3 4 5 6 7 mysql> CREATE FUNCTION add_nos(arg1 INT, arg2 INT) -> RETURNS INT LANGUAGE JAVASCRIPT AS -> $$ $> return arg1 + arg2 $> $$ -> ; Query OK, 0 rows affected (0.01 sec)
通过以下命令查看存储函数的创建语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 mysql> show create function add_nos\G *************************** 1. row *************************** Function: add_nos sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `add_nos`(arg1 INT, arg2 INT) RETURNS int LANGUAGE JAVASCRIPT AS $$ return arg1 + arg2 $$ character_set_client: utf8mb4 collation_connection: utf8mb4_0900_ai_ci Database Collation: utf8mb4_0900_ai_ci 1 row in set (0.00 sec)
执行该存储函数,验证其功能。
1 2 3 4 5 6 7 mysql> SELECT add_nos(20,25); +----------------+ | add_nos(20,25) | +----------------+ | 45 | +----------------+ 1 row in set (0.03 sec)
MLE 组件提供的会话信息方法
MLE组件提供了许多用于处理MLE用户会话的可加载函数。下面列出了这些函数。
mle_session_reset()
调用此函数将清理当前 MLE 会话状态,删除 mle_session_state() 中所有可观察的输出。它还会重置会话时区,以便后续调用 JavaScript 存储例程时使用会话中最新设置的时区。
1 2 3 4 5 6 7 mysql> select mle_session_reset(); +------------------------------------------+ | mle_session_reset() | +------------------------------------------+ | The session state is successfully reset. | +------------------------------------------+ 1 row in set (0.00 sec)
mle_session_state()
使用此可加载函数获取最近执行的 MLE 存储程序的会话信息。mle_session_state() 接受一个参数,即会话状态键(字符串),并显示会话状态值。
1 2 3 4 5 6 7 mysql> SELECT mle_session_state("is_active") AS '-ACTIVE-'; +----------+ | -ACTIVE- | +----------+ | 0 | +----------+ 1 row in set (0.00 sec)
mle_set_session_state()
此函数用于确定当前会话中将 MySQL 整数类型(TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT)转换为 JavaScript 值的规则。这些规则适用于 JavaScript 程序的输入参数以及结果集中的值。
1 2 3 4 5 6 7 mysql> SELECT mle_set_session_state('{"integer_type":"BIGINT"}'); +----------------------------------------------------+ | mle_set_session_state('{"integer_type":"BIGINT"}') | +----------------------------------------------------+ | 1 | +----------------------------------------------------+ 1 row in set (0.00 sec)
内存监控
调用 JavaScript 存储函数后,可通过如下方法查看 MLE 消耗的内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 mysql> SELECT * FROM performance_schema.memory_summary_global_by_event_name -> WHERE EVENT_NAME LIKE 'memory/language_component/%'\G *************************** 1. row *************************** EVENT_NAME: memory/language_component/session COUNT_ALLOC: 62 COUNT_FREE: 61 SUM_NUMBER_OF_BYTES_ALLOC: 15571 SUM_NUMBER_OF_BYTES_FREE: 15363 LOW_COUNT_USED: 0 CURRENT_COUNT_USED: 1 HIGH_COUNT_USED: 7 LOW_NUMBER_OF_BYTES_USED: 0 CURRENT_NUMBER_OF_BYTES_USED: 208 HIGH_NUMBER_OF_BYTES_USED: 2341 1 row in set (0.01 sec)
总结
MySQL 9.0 企业版和 MySQL HeatWave 对 JavaScript 存储程序的支持,这一特性不仅丰富了 MySQL 的功能集,更为开发者提供了更广阔的应用场景和更高效的开发方式。
Have a nice day ~
– / END / –