文档首页
MySQL 9.0 参考手册
相关文档 下载此手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  JavaScript 存储程序 - 会话信息和选项

27.3.5 JavaScript 存储程序 - 会话信息和选项

有关 MySQL 中存储例程的一般信息,请参见 第 27.2 节,“使用存储例程”.

MLE 组件提供了一些可加载函数,用于处理 MLE 用户会话。这些函数在下面列出并进行了描述。

  • mle_session_reset()

    调用此函数将清理当前 MLE 会话状态,删除来自 mle_session_state() 的任何可观察输出。它还会重置会话时区,以便后续调用 JavaScript 存储例程使用最近在会话中设置的时区。

  • mle_session_state()

    使用此可加载函数来获取有关最近执行的 MLE 存储程序的会话信息。 mle_session_state() 接受一个参数,会话状态键(字符串),并显示会话状态值。会话状态值的大小限制为最大 64K(相当于 16000 个 4 字节字符)。这是一个循环缓冲区;当可用空间已用完时,新条目将覆盖最旧的条目。下面列出了可能的会话状态键及其描述。

    • is_active:如果当前 MySQL 用户会话是 MLE 会话,则返回 1,否则返回 0

    • stdout:使用 console.log() 输出存储程序写入的任何内容。

    • stderr:使用 console.error() 输出存储程序写入的任何内容。

    • stack_trace:如果 MLE 存储程序的执行不成功,则此项包含堆栈跟踪,这可能有助于确定错误的根源。

      语法和类似错误在不成功的 CREATE FUNCTIONCREATE PROCEDURE 语句中遇到,不会在这里写入,只有在存储函数或存储过程执行期间引发的运行时错误才会写入。

    • stored_functions:返回当前会话中当前缓存的存储函数数量。

    • stored_procedures:返回当前会话中当前缓存的存储过程数量。

    • stored_programs:返回当前会话中当前缓存的存储程序(存储函数和存储过程)数量。

    会话状态键是文字字符串值,必须加引号。

    在调用任何 MLE 存储程序之前,所有三个会话状态值都是空的。退出客户端并重新启动会话会清除所有值。

    以下两个示例说明了如何检索会话状态值。我们首先创建一个存储过程 mle_states(),它显示所有会话状态值,如下所示。

    mysql> delimiter //
    mysql> CREATE PROCEDURE mle_states()
        -> BEGIN
        ->   SELECT
        ->     mle_session_state("is_active") AS '-ACTIVE-',
        ->     mle_session_state("stdout") AS '-STDOUT-',
        ->     mle_session_state("stderr") AS '-STDERR-',
        ->     mle_session_state("stack_trace") AS '-STACK-',
        ->     mle_session_state("stored_functions") AS '-FUNCS-',
        ->     mle_session_state("stored_procedures") AS '-PROCS-',
        ->     mle_session_state("stored_programs") AS '-PROGS-';
        -> END//
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> delimiter ;

    在运行任何 MLE 存储程序之前,来自 mle_states() 的输出中的所有值都是 0 或为空,如下所示。

    mysql> CALL mle_states();
    +----------+----------+----------+---------+---------+---------+---------+
    | -ACTIVE- | -STDOUT- | -STDERR- | -STACK- | -FUNCS- | -PROCS- | -PROGS- |
    +----------+----------+----------+---------+---------+---------+---------+
    | 0        |          |          |         | 0       | 0       | 0       |
    +----------+----------+----------+---------+---------+---------+---------+
    1 row in set (0.00 sec)
    
    Query OK, 0 rows affected (0.00 sec)

    现在,我们创建一个 JavaScript 存储过程 pc1(),它在短循环中使用 console.log()console.error() 多次写入 stdoutstderr,如下所示。

    mysql> CREATE PROCEDURE pc1()
        -> LANGUAGE JAVASCRIPT AS
        -> $$
        $>   let x = 0
        $>   
        $>   do  {
        $>     console.log(`This is message #${++x} to stdout.`)
        $>     console.error(`This is message #${x} to stderr.`)
        $>   }  
        $>   while(x < 3)
        $> $$
        -> ;
    Query OK, 0 rows affected (0.02 sec)

    在执行了上面所示的 CREATE PROCEDURE 语句之后,mle_states() 显示一个活动的 MLE 会话。尚未运行任何存储程序,因此没有程序被缓存;这意味着反映 JavaSCript 存储函数、过程和程序的列都显示 0。输出如下所示。

    mysql> CALL mle_states;
    +----------+----------+----------+---------+---------+---------+---------+
    | -ACTIVE- | -STDOUT- | -STDERR- | -STACK- | -FUNCS- | -PROCS- | -PROGS- |
    +----------+----------+----------+---------+---------+---------+---------+
    | 1        |          |          |         | 0       | 0       | 0       |
    +----------+----------+----------+---------+---------+---------+---------+
    1 row in set (0.00 sec)
    
    Query OK, 0 rows affected (0.00 sec)
    注意

    用反引号 (`) 字符引用字符串允许我们在输出中使用变量插值。如果您不熟悉这种引用机制,请参见 Mozilla Developer 上的 模板文字,了解更多信息。

    调用 pc1() 后跟 mle_states() 会产生以下结果。

    mysql> CALL pc1();
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> CALL mle_states()\G
    *************************** 1. row ***************************
    -ACTIVE-: 1
    -STDOUT-: This is message #1 to stdout.
    This is message #2 to stdout.
    This is message #3 to stdout.
    
    -STDERR-: This is message #1 to stderr.
    This is message #2 to stderr.
    This is message #3 to stderr.
    
     -STACK-: 
     -FUNCS-: 0
     -PROCS-: 1
     -PROGS-: 1
    1 row in set (0.00 sec)
    
    Query OK, 0 rows affected (0.00 sec)

    执行存储过程将启动一个 MLE 会话,因此 is_active (-ACTIVE-) 现在为 1

    在同一会话内对 stdoutstderr 的后续写入将附加到任何现有内容。要查看这一点,请再次调用 pc1(),然后检查 mle_states() 的输出,如下所示。

    mysql> CALL pc1();
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> CALL mle_states()\G
    *************************** 1. row ***************************
    -ACTIVE-: 1
    -STDOUT-: This is message #1 to stdout.
    This is message #2 to stdout.
    This is message #3 to stdout.
    This is message #1 to stdout.
    This is message #2 to stdout.
    This is message #3 to stdout.
    
    -STDERR-: This is message #1 to stderr.
    This is message #2 to stderr.
    This is message #3 to stderr.
    This is message #1 to stderr.
    This is message #2 to stderr.
    This is message #3 to stderr.
    
     -STACK-: 
     -FUNCS-: 0
     -PROCS-: 1
     -PROGS-: 1
    1 row in set (0.00 sec)
    
    Query OK, 0 rows affected (0.00 sec)

    由于 pc1() 未产生任何错误,因此堆栈跟踪保持为空。要测试堆栈跟踪,我们可以创建 pc1() 的修改副本,其中我们将对 console.log() 的引用更改为未定义的函数 console.lob(),如下所示。

    mysql> CREATE PROCEDURE pc2()
        -> LANGUAGE JAVASCRIPT AS
        -> $$
        $>   let x = 0
        $>   do  {
        $>     console.lob(`This is message #${++x} to stdout.`)
        $>     console.error(`This is message #${x} to stderr.`)
        $>   }  
        $>   while(x < 3)
        $> $$
        -> ;
    Query OK, 0 rows affected (0.02 sec)
    CREATE PROCEDURE pc2()
    LANGUAGE JAVASCRIPT AS
      $$
       let x = 0
       do  {
         console.lob(`This is message #${++x} to stdout.`)
         console.error(`This is message #${x} to stderr.`)
       }  
       while(x < 3)
      $$
    ;
    mysql> CREATE PROCEDURE pc2()
        -> LANGUAGE JAVASCRIPT AS
        -> $$
        $>   let x = 0
        $>   do  {
        $>     console.lob(`This is message #${++x} to stdout.`)
        $>     console.error(`This is message #${x} to stderr.`)
        $>   }  
        $>   while(x < 3)
        $> $$
        -> ;
    Query OK, 0 rows affected (0.02 sec)

    CREATE PROCEDURE 语句成功运行,但当我们尝试调用 pc2() 时,会出现错误,如下所示。

    mysql> CALL pc2();
    ERROR 6113 (HY000): JavaScript> TypeError: (intermediate value).lob is not a function

    在此之后,当我们再次调用 mle_states() 时,我们看到,由于我们处于同一会话中,stdoutstderr 字段仍然包含以前写入它们的内容。刚刚显示的错误的堆栈跟踪显示在输出的最后一列中。

    mysql> CALL mle_states()\G
    *************************** 1. row ***************************
    -ACTIVE-: 1
    -STDOUT-: This is message #1 to stdout.
    This is message #2 to stdout.
    This is message #3 to stdout.
    This is message #1 to stdout.
    This is message #2 to stdout.
    This is message #3 to stdout.
    
    -STDERR-: This is message #1 to stderr.
    This is message #2 to stderr.
    This is message #3 to stderr.
    This is message #1 to stderr.
    This is message #2 to stderr.
    This is message #3 to stderr.
    
    -STACK-: <js> pc2:3:6-54
    
    -FUNCS-: 0
    -PROCS-: 2
    -PROGS-: 2
    1 row in set (0.00 sec)
    
    Query OK, 0 rows affected (0.00 sec)

    此外,mle_session_state()stored_functionsstored_proceduresstored_programs 键的值分别为 022——我们创建了 2 个存储的 JavaScript 过程,并且没有 JavaScript 存储函数,总共 2 个 JavaScript 存储程序。

    堆栈跟踪不会在 JavaScript 存储程序调用之间持久存在。

    要清除 mle_states() 输出中所有字段中的所有信息,请调用 mle_session_reset(),如下所示。

    mysql> SELECT mle_session_reset();
    mysql> SELECT mle_session_reset();
    +------------------------------------------+
    | mle_session_reset()                      |
    +------------------------------------------+
    | The session state is successfully reset. |
    +------------------------------------------+
    1 row in set (0.00 sec)

    再次调用 mle_states() 会产生与初始结果相同的结果,即在使用任何存储的 JavaScript 存储程序之前。

    mysql> CALL mle_states;
    +----------+----------+----------+---------+---------+---------+---------+
    | -ACTIVE- | -STDOUT- | -STDERR- | -STACK- | -FUNCS- | -PROCS- | -PROGS- |
    +----------+----------+----------+---------+---------+---------+---------+
    | 0        |          |          |         | 0       | 0       | 0       |
    +----------+----------+----------+---------+---------+---------+---------+
    1 row in set (0.00 sec)
    
    Query OK, 0 rows affected (0.00 sec)

    或者,您可以使用 console.clear() 从 JavaScript 例程中清除 stdoutstderr

  • mle_set_session_state()

    MLE 组件提供此函数作为一种方法,用于确定当前会话中用于将 MySQL 整数类型 (TINYINTSMALLINTMEDIUMINTINTBIGINT) 转换为 JavaScript 值的规则。这些规则适用于 JavaScript 程序的输入参数以及结果集中的值。下面按名称列出了可能的转换规则。

    • BIGINT:始终转换为 JavaScript BigInt

    • STRING:始终转换为 JavaScript String

    • UNSAFE_BIGINT:如果该值是安全的,则转换为 JavaScript Number;否则转换为 JavaScript BigInt

    • UNSAFE_STRING:如果该值是安全的,则转换为 JavaScript Number;否则转换为 JavaScript String。如果未指定任何规则,则这是默认行为。

    在这些转换规则的上下文中,安全 表示要转换的值在 -(253-1) (-9007199254740991) 到 (253-1) (9007199254740991) 范围内,包括边界值。

    此函数仅在当前用户会话中没有缓存的存储程序时才能调用。成功时,该函数返回 1。否则,尝试调用它会引发错误,如下所示

    mysql> SELECT gcd(536, 1676); // Call JS stored function
    +----------------+
    | gcd(536, 1676) |
    +----------------+
    |              4 |
    +----------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT mle_set_session_state('{"integer_type":"BIGINT"}');
    ERROR 1123 (HY000): Can't initialize function 'mle_set_session_state'; Cannot
    set options of an active session. Please reset the session first.

    如错误消息所示,您必须重置会话以清除活动会话。为此,请使用 mle_session_reset(),如下所示

    mysql> SELECT mle_session_reset();
    +------------------------------------------+
    | mle_session_reset()                      |
    +------------------------------------------+
    | The session state is successfully reset. |
    +------------------------------------------+
    1 row in set (0.00 sec)

    现在,您可以像这样调用 mle_set_session_state()

    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 API Session 方法(如 sql()runSql()prepare())为该查询设置转换类型。有关更多信息和示例,请参阅 Session.sql() 的描述。

您可以通过查询 Performance Schema memory_summary_by_thread_by_event_namememory_summary_global_by_event_name 表来获取有关 MLE 组件资源使用情况的信息,使用键 memory/language_component/session,它跟踪每个 MLE 用户会话的内存使用情况。此键由 MLE 组件提供;它包含在 setup_instruments 表中,当安装 MLE 组件时,如下所示

mysql> SELECT * FROM performance_schema.setup_instruments 
     > WHERE NAME LIKE '%language_component%'\G
*************************** 1. row ***************************
         NAME: memory/language_component/session
      ENABLED: YES
        TIMED: NULL
   PROPERTIES: controlled_by_default
        FLAGS: controlled
   VOLATILITY: 0
DOCUMENTATION: Session-specific allocations for the Language component
1 row in set (0.00 sec)

在创建、执行或执行任何 JavaScript 存储程序之前,MLE 保持非活动状态,因此使用此键返回的结果为空,或者主要由零组成,如这里所示

mysql> SELECT * FROM performance_schema.memory_summary_by_thread_by_event_name 
    -> WHERE 
    ->   EVENT_NAME = 'memory/language_component/session' 
    ->     AND 
    ->   COUNT_ALLOC < 0\G
Empty set (0.02 sec)

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: 0
                  COUNT_FREE: 0
   SUM_NUMBER_OF_BYTES_ALLOC: 0
    SUM_NUMBER_OF_BYTES_FREE: 0
              LOW_COUNT_USED: 0
          CURRENT_COUNT_USED: 0
             HIGH_COUNT_USED: 0
    LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 0
   HIGH_NUMBER_OF_BYTES_USED: 0
1 row in set (0.01 sec)

在调用 JavaScript 存储函数后,相同的查询现在反映了 MLE 占用的内存,如这里所示

mysql> SELECT * FROM performance_schema.memory_summary_by_thread_by_event_name 
    -> WHERE 
    ->   EVENT_NAME = 'memory/language_component/session' 
    ->     AND 
    ->   COUNT_ALLOC < 0\G
*************************** 1. row ***************************
                   THREAD_ID: 46
                  EVENT_NAME: memory/language_component/session
                 COUNT_ALLOC: 25
                  COUNT_FREE: 20
   SUM_NUMBER_OF_BYTES_ALLOC: 4445
    SUM_NUMBER_OF_BYTES_FREE: 2989
              LOW_COUNT_USED: 0
          CURRENT_COUNT_USED: 5
             HIGH_COUNT_USED: 14
    LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 1456
   HIGH_NUMBER_OF_BYTES_USED: 3239
1 row in set (0.00 sec)

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: 25
                  COUNT_FREE: 20
   SUM_NUMBER_OF_BYTES_ALLOC: 4445
    SUM_NUMBER_OF_BYTES_FREE: 2989
              LOW_COUNT_USED: 0
          CURRENT_COUNT_USED: 5
             HIGH_COUNT_USED: 14
    LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 1456
   HIGH_NUMBER_OF_BYTES_USED: 3239
1 row in set (0.00 sec)

有关这些和相关 Performance Schema 表的更多信息,请参阅 第 29.12.20.10 节,“内存摘要表”

给定用户会话中 MLE 组件的内存使用量受 connection_memory_limit 服务器系统变量施加的限制。有关更多信息,请参阅此变量的描述。