8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

MySQL 8.4 参考手册 / 27 存储对象 / 27.7 存储程序二进制日志记录
中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 100%

27.7 存储程序二进制日志27.7 Stored Program Binary Logging

二进制日志包含关于修改数据库内容的 SQL 语句的信息。这些信息以“事件”的形式存储,用于描述这些修改。(二进制日志事件不同于计划事件存储对象。)二进制日志有两个重要的用途:The binary log contains information about SQL statements that modify database contents. This information is stored in the form of “events” that describe the modifications. (Binary log events differ from scheduled event stored objects.) The binary log has two important purposes:

  • 在复制中,二进制日志在源复制服务器上用作要发送到副本服务器的语句记录。源服务器将其二进制日志中包含的事件发送给其副本,副本执行这些事件,以实现与源服务器相同的数据更改。参见 第 19.2 节,“复制实现”。For replication, the binary log is used on source replication servers as a record of the statements to be sent to replica servers. The source sends the events contained in its binary log to its replicas, which execute those events to make the same data changes that were made on the source. See Section 19.2, “Replication Implementation”.

  • 某些数据恢复操作需要使用二进制日志。在备份文件恢复后,备份创建后记录的二进制日志事件会被重新执行。这些事件使数据库从备份时点更新到最新状态。参见 第 9.3.2 节,“使用备份进行恢复”。Certain data recovery operations require use of the binary log. After a backup file has been restored, the events in the binary log that were recorded after the backup was made are re-executed. These events bring databases up to date from the point of the backup. See Section 9.3.2, “Using Backups for Recovery”.

然而,如果日志记录发生在语句级别,对于存储程序(存储过程和函数、触发器和事件),存在某些二进制日志问题:However, if logging occurs at the statement level, there are certain binary logging issues with respect to stored programs (stored procedures and functions, triggers, and events):

  • 在某些情况下,一个语句可能会对源和副本上的不同行集合产生影响。In some cases, a statement might affect different sets of rows on source and replica.

  • 在副本上执行的复制语句由副本的应用线程处理。除非您实施复制权限检查(参见 第 19.3.3 节,“复制权限检查”),否则应用线程拥有完整权限。在这种情况下,存储过程可能在源服务器和副本服务器上走不同的执行路径,因此用户可能编写一个仅在副本上执行的危险语句的例程。Replicated statements executed on a replica are processed by the replica's applier thread. Unless you implement replication privilege checks (see Section 19.3.3, “Replication Privilege Checks”), the applier thread has full privileges. In this situation, it is possible for a procedure to follow different execution paths on source and replica servers, so a user could write a routine containing a dangerous statement that executes only on the replica.

  • 如果修改数据的存储程序是非确定性的,那么它是不可重复的。这可能导致源和副本上的数据不同,或者导致恢复的数据与原始数据不同。If a stored program that modifies data is nondeterministic, it is not repeatable. This can result in different data on source and replica, or cause restored data to differ from the original data.

本节描述了 MySQL 如何处理存储程序的二进制日志。它说明了当前实现对使用存储程序所施加的条件,以及您可以做些什么来避免日志问题。它还提供了关于这些条件原因的额外信息。This section describes how MySQL handles binary logging for stored programs. It states the current conditions that the implementation places on the use of stored programs, and what you can do to avoid logging problems. It also provides additional information about the reasons for these conditions.

除非另有说明,此处的说明假设服务器已启用二进制日志(参见 第 7.4.4 节,“二进制日志”)。如果未启用二进制日志,则无法进行复制,二进制日志也无法用于数据恢复。默认情况下二进制日志是启用的,只有在启动服务器时使用 --skip-log-bin 或 --disable-log-bin 才会被禁用。Unless noted otherwise, the remarks here assume that binary logging is enabled on the server (see Section 7.4.4, “The Binary Log”.) If the binary log is not enabled, replication is not possible, nor is the binary log available for data recovery. Binary logging is enabled by default, and is disabled only if you start the server with --skip-log-bin or --disable-log-bin at startup.

一般来说,这里描述的问题是由于在 SQL 语句级别进行二进制日志记录(基于语句的二进制日志记录)时发生的。如果您使用基于行的二进制日志记录,日志将包含执行 SQL 语句所导致的单个行的更改。当例程或触发器执行时,记录的是行的更改,而不是导致更改的语句。对于存储过程,这意味着 CALL 语句不会被记录。对于存储函数,记录的是函数内部所作的行更改,而不是函数调用。对于触发器,记录的是触发器所作的行更改。在副本端,只能看到行更改,而看不到存储程序的调用。In general, the issues described here result when binary logging occurs at the SQL statement level (statement-based binary logging). If you use row-based binary logging, the log contains changes made to individual rows as a result of executing SQL statements. When routines or triggers execute, row changes are logged, not the statements that make the changes. For stored procedures, this means that the CALL statement is not logged. For stored functions, row changes made within the function are logged, not the function invocation. For triggers, row changes made by the trigger are logged. On the replica side, only the row changes are seen, not the stored program invocation.

混合格式二进制日志记录(binlog_format=MIXED)使用基于语句的二进制日志记录,除非只有基于行的二进制日志记录才能保证生成正确结果。在混合格式下,当存储函数、存储过程、触发器、事件或预处理语句包含任何对基于语句的二进制日志记录不安全的内容时,整个语句将被标记为不安全并以行格式记录。用于创建和删除过程、函数、触发器和事件的语句始终是安全的,并以语句格式记录。有关基于行、混合和基于语句日志记录的更多信息,以及如何确定安全和不安全语句,请参阅 第 19.2.1 节,“复制格式”。Mixed format binary logging (binlog_format=MIXED) uses statement-based binary logging, except for cases where only row-based binary logging is guaranteed to lead to proper results. With mixed format, when a stored function, stored procedure, trigger, event, or prepared statement contains anything that is not safe for statement-based binary logging, the entire statement is marked as unsafe and logged in row format. The statements used to create and drop procedures, functions, triggers, and events are always safe, and are logged in statement format. For more information about row-based, mixed, and statement-based logging, and how safe and unsafe statements are determined, see Section 19.2.1, “Replication Formats”.

MySQL 中存储函数的使用条件可以总结如下。这些条件不适用于存储过程或事件调度器事件,并且只有在启用二进制日志记录时才适用。The conditions on the use of stored functions in MySQL can be summarized as follows. These conditions do not apply to stored procedures or Event Scheduler events and they do not apply unless binary logging is enabled.

  • 要创建或修改存储函数,除了通常所需的 CREATE ROUTINE 或 ALTER ROUTINE 权限之外,还必须拥有 SET_ANY_DEFINER 权限。(根据函数定义中的 DEFINER 值,无论是否启用二进制日志,都可能需要 SET_ANY_DEFINER 权限。参见 第 15.1.17 节,“CREATE PROCEDURE 和 CREATE FUNCTION 语句”。)To create or alter a stored function, you must have the SET_ANY_DEFINER privilege, in addition to the CREATE ROUTINE or ALTER ROUTINE privilege that is normally required. (Depending on the DEFINER value in the function definition, SET_ANY_DEFINER might be required regardless of whether binary logging is enabled. See Section 15.1.17, “CREATE PROCEDURE and CREATE FUNCTION Statements”.)

  • 当您创建存储函数时,必须声明它是确定性的或不修改数据。否则,它可能对数据恢复或复制不安全。When you create a stored function, you must declare either that it is deterministic or that it does not modify data. Otherwise, it may be unsafe for data recovery or replication.

    默认情况下,对于 CREATE FUNCTION 语句,要被接受,必须显式指定 DETERMINISTIC、NO SQL 或 READS SQL DATA 中的至少一项。否则会发生错误:By default, for a CREATE FUNCTION statement to be accepted, at least one of DETERMINISTIC, NO SQL, or READS SQL DATA must be specified explicitly. Otherwise an error occurs:

    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)
    

    此函数是确定性的(且不修改数据),因此是安全的:This function is deterministic (and does not modify data), so it is safe:

    CREATE FUNCTION f1(i INT)
    RETURNS INT
    DETERMINISTIC
    READS SQL DATA
    BEGIN
      RETURN i;
    END;
    

    此函数使用 UUID(),它不是确定性的,因此该函数也不是确定性的,并且不安全:This function uses UUID(), which is not deterministic, so the function also is not deterministic and is not safe:

    CREATE FUNCTION f2()
    RETURNS CHAR(36) CHARACTER SET utf8mb4
    BEGIN
      RETURN UUID();
    END;
    

    此函数修改数据,因此可能不安全:This function modifies data, so it may not be safe:

    CREATE FUNCTION f3(p_id INT)
    RETURNS INT
    BEGIN
      UPDATE t SET modtime = NOW() WHERE id = p_id;
      RETURN ROW_COUNT();
    END;
    

    对函数性质的评估是基于创建者的“诚信”。MySQL 并不检查被声明为 DETERMINISTIC 的函数是否包含会产生非确定性结果的语句。Assessment of the nature of a function is based on the “honesty” of the creator. MySQL does not check that a function declared DETERMINISTIC is free of statements that produce nondeterministic results.

  • 当您尝试执行存储函数时,如果设置了binlog_format=STATEMENT,则必须在函数定义中指定DETERMINISTIC关键字。如果没有指定,将会生成错误并且函数无法运行,除非指定log_bin_trust_function_creators=1来覆盖此检查(见下文)。对于递归函数调用,仅在最外层调用中需要DETERMINISTIC关键字。如果使用基于行或混合的二进制日志,即使函数定义时没有DETERMINISTIC关键字,该语句仍然会被接受并复制。When you attempt to execute a stored function, if binlog_format=STATEMENT is set, the DETERMINISTIC keyword must be specified in the function definition. If this is not the case, an error is generated and the function does not run, unless log_bin_trust_function_creators=1 is specified to override this check (see below). For recursive function calls, the DETERMINISTIC keyword is required on the outermost call only. If row-based or mixed binary logging is in use, the statement is accepted and replicated even if the function was defined without the DETERMINISTIC keyword.

  • 由于 MySQL 在创建时不会检查函数是否真的确定性,带有 DETERMINISTIC 关键字的存储函数调用可能执行对基于语句的日志记录不安全的操作,或调用包含不安全语句的函数或过程。如果在设置 binlog_format=STATEMENT 时发生这种情况,将发出警告信息。如果使用基于行或混合的二进制日志记录,则不会发出警告,并且该语句将以基于行的格式进行复制。Because MySQL does not check if a function really is deterministic at creation time, the invocation of a stored function with the DETERMINISTIC keyword might carry out an action that is unsafe for statement-based logging, or invoke a function or procedure containing unsafe statements. If this occurs when binlog_format=STATEMENT is set, a warning message is issued. If row-based or mixed binary logging is in use, no warning is issued, and the statement is replicated in row-based format.

  • 要放宽有关函数创建的前述条件(即您必须拥有 SUPER 权限,并且函数必须声明为确定性或不修改数据),请将全局 log_bin_trust_function_creators 系统变量设置为 1。默认情况下,该变量的值为 0,但您可以这样更改:To relax the preceding conditions on function creation (that you must have the SUPER privilege and that a function must be declared deterministic or to not modify data), set the global log_bin_trust_function_creators system variable to 1. By default, this variable has a value of 0, but you can change it like this:

    mysql> SET GLOBAL log_bin_trust_function_creators = 1;
    

    您也可以在服务器启动时设置此变量。You can also set this variable at server startup.

    如果未启用二进制日志,log_bin_trust_function_creators 不适用。除非如前所述,函数定义中的 DEFINER 值需要,否则创建函数不需要 SUPER 权限。If binary logging is not enabled, log_bin_trust_function_creators does not apply. SUPER is not required for function creation unless, as described previously, the DEFINER value in the function definition requires it.

  • 有关可能对复制不安全的内置函数(因此使用它们的存储函数也可能不安全)的信息,请参见 第 19.5.1 节,“复制功能和问题”。For information about built-in functions that may be unsafe for replication (and thus cause stored functions that use them to be unsafe as well), see Section 19.5.1, “Replication Features and Issues”.

触发器类似于存储函数,因此关于函数的前述说明也适用于触发器,但有以下例外:CREATE TRIGGER 没有可选的 DETERMINISTIC 特性,因此触发器被假定为始终确定性。然而,这一假设在某些情况下可能无效。例如,UUID() 函数是非确定性的(并且不进行复制)。在触发器中使用此类函数时请小心。Triggers are similar to stored functions, so the preceding remarks regarding functions also apply to triggers with the following exception: CREATE TRIGGER does not have an optional DETERMINISTIC characteristic, so triggers are assumed to be always deterministic. However, this assumption might be invalid in some cases. For example, the UUID() function is nondeterministic (and does not replicate). Be careful about using such functions in triggers.

触发器可以更新表,因此如果您没有所需的权限,在使用 CREATE TRIGGER 时会出现类似于存储函数的错误消息。在副本端,副本使用触发器的 DEFINER 属性来确定哪个用户被视为触发器的创建者。Triggers can update tables, so error messages similar to those for stored functions occur with CREATE TRIGGER if you do not have the required privileges. On the replica side, the replica uses the trigger DEFINER attribute to determine which user is considered to be the creator of the trigger.

本节的其余部分提供了有关日志记录实现及其影响的更多细节。除非您对当前日志相关的存储例程使用条件的背景原因感兴趣,否则无需阅读。本讨论仅适用于基于语句的日志记录,而不适用于基于行的日志记录,但第一个项目除外:CREATE 和 DROP 语句无论在何种日志模式下都会以语句方式记录。The rest of this section provides additional detail about the logging implementation and its implications. You need not read it unless you are interested in the background on the rationale for the current logging-related conditions on stored routine use. This discussion applies only for statement-based logging, and not for row-based logging, with the exception of the first item: CREATE and DROP statements are logged as statements regardless of the logging mode.

  • 服务器将 CREATE EVENT、CREATE PROCEDURE、CREATE FUNCTION、ALTER EVENT、ALTER PROCEDURE、ALTER FUNCTION、DROP EVENT、DROP PROCEDURE 以及 DROP FUNCTION 语句写入二进制日志。The server writes CREATE EVENT, CREATE PROCEDURE, CREATE FUNCTION, ALTER EVENT, ALTER PROCEDURE, ALTER FUNCTION, DROP EVENT, DROP PROCEDURE, and DROP FUNCTION statements to the binary log.

  • 如果存储函数改变数据并且出现在本来不会被记录的语句中,则其调用会作为 SELECT 语句被记录。这可以防止由于在非记录语句中使用存储函数而导致的数据更改无法复制。例如,SELECT 语句不会写入二进制日志,但一个 SELECT 可能会调用修改数据的存储函数。为此,当给定函数进行更改时,会将 SELECT func_name() 语句写入二进制日志。假设在源服务器上执行以下语句:A stored function invocation is logged as a SELECT statement if the function changes data and occurs within a statement that would not otherwise be logged. This prevents nonreplication of data changes that result from use of stored functions in nonlogged statements. For example, SELECT statements are not written to the binary log, but a SELECT might invoke a stored function that makes changes. To handle this, a SELECT func_name() statement is written to the binary log when the given function makes a change. Suppose that the following statements are executed on the source server:

    CREATE FUNCTION f1(a INT) RETURNS INT
    BEGIN
      IF (a < 3) THEN
        INSERT INTO t2 VALUES (a);
      END IF;
      RETURN 0;
    END;
    
    CREATE TABLE t1 (a INT);
    INSERT INTO t1 VALUES (1),(2),(3);
    
    SELECT f1(a) FROM t1;
    

    当 SELECT 语句执行时,函数 f1() 会被调用三次。其中两次调用会插入一行数据,并且 MySQL 会为每次调用记录一个 SELECT 语句。也就是说,MySQL 会将以下语句写入二进制日志:When the SELECT statement executes, the function f1() is invoked three times. Two of those invocations insert a row, and MySQL logs a SELECT statement for each of them. That is, MySQL writes the following statements to the binary log:

    SELECT f1(1);
    SELECT f1(2);
    

    当存储函数调用一个导致错误的存储过程时,服务器还会记录该函数调用的 SELECT 语句。在这种情况下,服务器会将该 SELECT 语句及预期的错误代码写入日志。在副本上,如果发生相同的错误,这是预期结果,复制会继续。否则,复制会停止。The server also logs a SELECT statement for a stored function invocation when the function invokes a stored procedure that causes an error. In this case, the server writes the SELECT statement to the log along with the expected error code. On the replica, if the same error occurs, that is the expected result and replication continues. Otherwise, replication stops.

  • 记录存储函数调用而不是函数执行的语句对复制存在安全隐患,这种隐患来自两个因素:Logging stored function invocations rather than the statements executed by a function has a security implication for replication, which arises from two factors:

    • 函数在源服务器和副本服务器上可能会走不同的执行路径。It is possible for a function to follow different execution paths on source and replica servers.

    • 在副本上执行的语句由副本的应用线程处理。除非你实现了复制权限检查(见 第 19.3.3 节,“复制权限检查”),否则应用线程拥有全部权限。Statements executed on a replica are processed by the replica's applier thread. Unless you implement replication privilege checks (see Section 19.3.3, “Replication Privilege Checks”), the applier thread has full privileges.

    其含义是,尽管用户必须拥有 CREATE ROUTINE 权限才能创建函数,但用户可以编写包含危险语句的函数,该语句仅在副本上执行,由拥有全部权限的线程处理。例如,如果源服务器和副本服务器的服务器 ID 分别为 1 和 2,则源服务器上的用户可以创建并调用不安全函数 unsafe_func(),如下所示:The implication is that although a user must have the CREATE ROUTINE privilege to create a function, the user can write a function containing a dangerous statement that executes only on the replica where it is processed by a thread that has full privileges. For example, if the source and replica servers have server ID values of 1 and 2, respectively, a user on the source server could create and invoke an unsafe function unsafe_func() as follows:

    mysql> delimiter //
    mysql> CREATE FUNCTION unsafe_func () RETURNS INT
        -> BEGIN
        ->   IF @@server_id=2 THEN dangerous_statement; END IF;
        ->   RETURN 1;
        -> END;
        -> //
    mysql> delimiter ;
    mysql> INSERT INTO t VALUES(unsafe_func());
    

    CREATE FUNCTION 和 INSERT 语句会被写入二进制日志,因此副本会执行它们。因为副本的应用线程拥有完整权限,所以它会执行危险的语句。因此,函数调用在源端和副本端的效果不同,并且不安全进行复制。The CREATE FUNCTION and INSERT statements are written to the binary log, so the replica executes them. Because the replica's applier thread has full privileges, it executes the dangerous statement. Thus, the function invocation has different effects on the source and replica and is not replication-safe.

    为了防止在启用了二进制日志的服务器上出现这种危险,存储函数的创建者除了需要通常的 CREATE ROUTINE 权限外,还必须拥有 SUPER 权限。类似地,要使用 ALTER FUNCTION,除了需要 ALTER ROUTINE 权限外,还必须拥有 SUPER 权限。如果没有 SUPER 权限,将会发生错误:To guard against this danger for servers that have binary logging enabled, stored function creators must have the SUPER privilege, in addition to the usual CREATE ROUTINE privilege that is required. Similarly, to use ALTER FUNCTION, you must have the SUPER privilege in addition to the ALTER ROUTINE privilege. Without the SUPER privilege, an error occurs:

    ERROR 1419 (HY000): You do not have the SUPER privilege and
    binary logging is enabled (you *might* want to use the less safe
    log_bin_trust_function_creators variable)
    

    如果您不想要求函数创建者拥有 SUPER 特权(例如,如果所有在系统上拥有 CREATE ROUTINE 特权的用户都是经验丰富的应用程序开发者),请将全局 log_bin_trust_function_creators 系统变量设置为 1。您也可以在服务器启动时设置此变量。如果未启用二进制日志,log_bin_trust_function_creators 不适用。除非如前所述,在函数定义中 DEFINER 的值要求,否则创建函数不需要 SUPER 特权。If you do not want to require function creators to have the SUPER privilege (for example, if all users with the CREATE ROUTINE privilege on your system are experienced application developers), set the global log_bin_trust_function_creators system variable to 1. You can also set this variable at server startup. If binary logging is not enabled, log_bin_trust_function_creators does not apply. SUPER is not required for function creation unless, as described previously, the DEFINER value in the function definition requires it.

  • 建议无论您对函数创建者的权限作出何种选择,都使用复制权限检查。可以设置复制权限检查以确保只有预期的和相关的操作被授权用于复制通道。有关执行此操作的说明,请参见 第 19.3.3 节,“复制权限检查”。The use of replication privilege checks recommended regardless of any choices you make about privileges for function creators. Replication privilege checks can be set up to ensure that only expected and relevant operations are authorized for the replication channel. For instructions to do this, see Section 19.3.3, “Replication Privilege Checks”.

  • 如果执行更新的函数是非确定性的,它是不可重复的。这可能有两个不良影响:If a function that performs updates is nondeterministic, it is not repeatable. This can have two undesirable effects:

    • 会导致副本与源不同。It causes a replica to differ from the source.

    • 恢复的数据与原始数据不匹配。Restored data does not match the original data.

    为了解决这些问题,MySQL 强制以下要求:在源服务器上,除非您声明函数是确定性的或不修改数据,否则拒绝创建和修改函数。这里适用两组函数特性:To deal with these problems, MySQL enforces the following requirement: On a source server, creation and alteration of a function is refused unless you declare the function to be deterministic or to not modify data. Two sets of function characteristics apply here:

    • DETERMINISTIC 和 NOT DETERMINISTIC 特性表示函数对于给定输入是否总是产生相同的结果。如果未提供任何特性,默认值为 NOT DETERMINISTIC。要声明一个函数是确定性的,必须显式指定 DETERMINISTIC。The DETERMINISTIC and NOT DETERMINISTIC characteristics indicate whether a function always produces the same result for given inputs. The default is NOT DETERMINISTIC if neither characteristic is given. To declare that a function is deterministic, you must specify DETERMINISTIC explicitly.

    • CONTAINS SQL、NO SQL、READS SQL DATA 和 MODIFIES SQL DATA 特性提供了函数是否读取或写入数据的信息。NO SQL 或 READS SQL DATA 表示函数不会更改数据,但必须显式指定其中一个,因为如果未提供任何特性,则默认值为 CONTAINS SQL。The CONTAINS SQL, NO SQL, READS SQL DATA, and MODIFIES SQL DATA characteristics provide information about whether the function reads or writes data. Either NO SQL or READS SQL DATA indicates that a function does not change data, but you must specify one of these explicitly because the default is CONTAINS SQL if no characteristic is given.

    默认情况下,对于 CREATE FUNCTION 语句,要被接受,必须显式指定 DETERMINISTIC、NO SQL 或 READS SQL DATA 中的至少一项。否则会发生错误:By default, for a CREATE FUNCTION statement to be accepted, at least one of DETERMINISTIC, NO SQL, or READS SQL DATA must be specified explicitly. Otherwise an error occurs:

    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,则不再要求函数必须是确定性的或不修改数据。If you set log_bin_trust_function_creators to 1, the requirement that functions be deterministic or not modify data is dropped.

  • 存储过程调用记录的是语句级别,而不是 CALL 级别。也就是说,服务器不记录 CALL 语句,而是记录过程内实际执行的那些语句。因此,源服务器上发生的相同更改也会在副本上发生。这可以防止由于过程在不同机器上有不同执行路径而可能导致的问题。Stored procedure calls are logged at the statement level rather than at the CALL level. That is, the server does not log the CALL statement, it logs those statements within the procedure that actually execute. As a result, the same changes that occur on the source server also occur on replicas. This prevents problems that could result from a procedure having different execution paths on different machines.

    通常情况下,在存储过程中执行的语句会按照与单独执行语句时相同的规则写入二进制日志。在记录过程语句时需要特别注意,因为在存储过程中的语句执行与非过程上下文中的执行并不完全相同:In general, statements executed within a stored procedure are written to the binary log using the same rules that would apply were the statements to be executed in standalone fashion. Some special care is taken when logging procedure statements because statement execution within procedures is not quite the same as in nonprocedure context:

    • 要记录的语句可能包含对存储过程局部变量的引用。这些变量在存储过程上下文之外不存在,因此引用此类变量的语句不能被字面记录。相反,每次引用局部变量时,在日志记录时会用以下结构替代: A statement to be logged might contain references to local procedure variables. These variables do not exist outside of stored procedure context, so a statement that refers to such a variable cannot be logged literally. Instead, each reference to a local variable is replaced by this construct for logging purposes:

      NAME_CONST(var_name, var_value)
      

      var_name 是局部变量名,var_value 是一个常量,表示在记录该语句时变量的值。NAME_CONST() 的值为 var_value,并且其 “name” 为 var_name。因此,如果直接调用此函数,会得到类似如下的结果:var_name is the local variable name, and var_value is a constant indicating the value that the variable has at the time the statement is logged. NAME_CONST() has a value of var_value, and a “name” of var_name. Thus, if you invoke this function directly, you get a result like this:

      mysql> SELECT NAME_CONST('myname', 14);
      +--------+
      | myname |
      +--------+
      |     14 |
      +--------+
      

      NAME_CONST() 使日志中的独立语句能够在副本上执行,效果与在存储过程中的源上执行原语句相同。NAME_CONST() enables a logged standalone statement to be executed on a replica with the same effect as the original statement that was executed on the source within a stored procedure.

      在源列表达式引用本地变量时,使用 NAME_CONST() 可能会导致 CREATE TABLE ... SELECT 语句出现问题。将这些引用转换为 NAME_CONST() 表达式可能导致源服务器和副本服务器上的列名不同,或者列名过长而不合法。解决方法是为引用本地变量的列提供别名。当 myvar 的值为 1 时,请考虑以下语句:The use of NAME_CONST() can result in a problem for CREATE TABLE ... SELECT statements when the source column expressions refer to local variables. Converting these references to NAME_CONST() expressions can result in column names that are different on the source and replica servers, or names that are too long to be legal column identifiers. A workaround is to supply aliases for columns that refer to local variables. Consider this statement when myvar has a value of 1:

      CREATE TABLE t1 SELECT myvar;
      

      它被重写为如下:This is rewritten as follows:

      CREATE TABLE t1 SELECT NAME_CONST(myvar, 1);
      

      为了确保源表和副本表具有相同的列名,请这样编写语句:To ensure that the source and replica tables have the same column names, write the statement like this:

      CREATE TABLE t1 SELECT myvar AS myvar;
      

      重写后的语句如下:The rewritten statement becomes:

      CREATE TABLE t1 SELECT NAME_CONST(myvar, 1) AS myvar;
      
    • 要记录的语句可能包含对用户定义变量的引用。为处理这种情况,MySQL 会将 SET 语句写入二进制日志,以确保该变量在副本上存在,并且其值与源上相同。例如,如果语句引用变量 @my_var,则在二进制日志中,该语句之前会有以下语句,其中 value 是源上 @my_var 的值:A statement to be logged might contain references to user-defined variables. To handle this, MySQL writes a SET statement to the binary log to make sure that the variable exists on the replica with the same value as on the source. For example, if a statement refers to a variable @my_var, that statement is preceded in the binary log by the following statement, where value is the value of @my_var on the source:

      SET @my_var = value;
      
    • 过程调用可以发生在已提交或已回滚的事务中。事务上下文被考虑在内,以便过程执行的事务性方面能够正确复制。也就是说,服务器记录在过程内实际执行并修改数据的语句,并根据需要记录BEGIN、COMMIT和ROLLBACK语句。例如,如果一个过程仅更新事务表,并且在一个被回滚的事务中执行,则这些更新不会被记录。如果该过程发生在已提交的事务中,BEGIN和COMMIT语句会与更新一起记录。对于在已回滚事务中执行的过程,其语句的记录遵循与在单独执行语句时相同的规则:Procedure calls can occur within a committed or rolled-back transaction. Transactional context is accounted for so that the transactional aspects of procedure execution are replicated correctly. That is, the server logs those statements within the procedure that actually execute and modify data, and also logs BEGIN, COMMIT, and ROLLBACK statements as necessary. For example, if a procedure updates only transactional tables and is executed within a transaction that is rolled back, those updates are not logged. If the procedure occurs within a committed transaction, BEGIN and COMMIT statements are logged with the updates. For a procedure that executes within a rolled-back transaction, its statements are logged using the same rules that would apply if the statements were executed in standalone fashion:

      • 事务表的更新不会被记录。Updates to transactional tables are not logged.

      • 非事务表的更新会被记录,因为回滚不会取消它们。Updates to nontransactional tables are logged because rollback does not cancel them.

      • 事务表和非事务表混合的更新会被记录,且包围在BEGIN和ROLLBACK之间,以便副本执行与源相同的更改和回滚。Updates to a mix of transactional and nontransactional tables are logged surrounded by BEGIN and ROLLBACK so that replicas make the same changes and rollbacks as on the source.

  • 如果存储过程从存储函数内部调用,则该存储过程的调用 不会 在语句级别写入二进制日志。在这种情况下,唯一被记录的只是调用该函数的语句(如果它发生在被记录的语句中)或 DO 语句(如果它发生在未被记录的语句中)。因此,即使该存储过程本身是安全的,也应在使用调用过程的存储函数时谨慎。A stored procedure call is not written to the binary log at the statement level if the procedure is invoked from within a stored function. In that case, the only thing logged is the statement that invokes the function (if it occurs within a statement that is logged) or a DO statement (if it occurs within a statement that is not logged). For this reason, care should be exercised in the use of stored functions that invoke a procedure, even if the procedure is otherwise safe in itself.