This section describes how to write a server-side audit
          plugin, using the example plugin found in the
          plugin/audit_null directory of MySQL source
          distributions. The audit_null.c and
          audit_null_variables.h source files in
          that directory implement an audit plugin named
          NULL_AUDIT.
        
Other examples of plugins that use the audit plugin API are the query rewrite plugin (see The Rewriter Query Rewrite Plugin) and the Version Tokens plugin (see Version Tokens).
          Within the server, the pluggable audit interface is
          implemented in the sql_audit.h and
          sql_audit.cc files in the
          sql directory of MySQL source
          distributions. Additionally, several places in the server call
          the audit interface when an auditable event occurs, so that
          registered audit plugins can be notified about the event if
          necessary. To see where such calls occur, search the server
          source files for invocations of functions with names of the
          form
          mysql_audit_.
          Audit notification occurs for server operations such as these:
        xxx()
- Client connect and disconnect events 
- Writing a message to the general query log (if the log is enabled) 
- Writing a message to the error log 
- Sending a query result to a client 
To write an audit plugin, include the following header file in the plugin source file. Other MySQL or general header files might also be needed, depending on the plugin capabilities and requirements.
#include <mysql/plugin_audit.h>
          plugin_audit.h includes
          plugin.h, so you need not include the
          latter file explicitly. plugin.h defines
          the MYSQL_AUDIT_PLUGIN server plugin type
          and the data structures needed to declare the plugin.
          plugin_audit.h defines data structures
          specific to audit plugins.
        
            An audit plugin, like any MySQL server plugin, has a general
            plugin descriptor (see
            Section 4.4.2.1, “Server Plugin Library and Plugin Descriptors”) and a
            type-specific plugin descriptor. In
            audit_null.c, the general descriptor
            for audit_null looks like this:
          
mysql_declare_plugin(audit_null)
{
  MYSQL_AUDIT_PLUGIN,         /* type                            */
  &audit_null_descriptor,     /* descriptor                      */
  "NULL_AUDIT",               /* name                            */
  "Oracle Corporation",       /* author                          */
  "Simple NULL Audit",        /* description                     */
  PLUGIN_LICENSE_GPL,
  audit_null_plugin_init,     /* init function (when loaded)     */
  audit_null_plugin_deinit,   /* deinit function (when unloaded) */
  0x0003,                     /* version                         */
  simple_status,              /* status variables                */
  system_variables,           /* system variables                */
  NULL,
  0,
}
mysql_declare_plugin_end;
            The first member, MYSQL_AUDIT_PLUGIN,
            identifies this plugin as an audit plugin.
          
            audit_null_descriptor points to the
            type-specific plugin descriptor, described later.
          
            The name member
            (NULL_AUDIT) indicates the name to use
            for references to the plugin in statements such as
            INSTALL PLUGIN or
            UNINSTALL PLUGIN. This is
            also the name displayed by
            INFORMATION_SCHEMA.PLUGINS or
            SHOW PLUGINS.
          
            The audit_null_plugin_init initialization
            function performs plugin initialization when the plugin is
            loaded. The audit_null_plugin_deinit
            function performs cleanup when the plugin is unloaded.
          
            The general plugin descriptor also refers to
            simple_status and
            system_variables, structures that expose
            several status and system variables. When the plugin is
            enabled, these variables can be inspected using
            SHOW statements
            (SHOW STATUS,
            SHOW VARIABLES) or the
            appropriate Performance Schema tables.
          
            The simple_status structure declares
            several status variables with names of the form
            Audit_null_.
            xxxNULL_AUDIT increments the
            Audit_null_called status variable for
            every notification that it receives. The other status
            variables are more specific and
            NULL_AUDIT increments them only for
            notifications of specific events.
          
            system_variables is an array of system
            variable elements, each of which is defined using a
            MYSQL_THDVAR_
            macro. These system variables have names of the form
            xxxnull_audit_.
            These variables can be used to communicate with the plugin
            at runtime.
          xxx
            The audit_null_descriptor value in the
            general plugin descriptor points to the type-specific plugin
            descriptor. For audit plugins, this descriptor has the
            following structure (defined in
            plugin_audit.h):
          
struct st_mysql_audit
{
  int interface_version;
  void (*release_thd)(MYSQL_THD);
  int (*event_notify)(MYSQL_THD, mysql_event_class_t, const void *);
  unsigned long class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
};The type-specific descriptor for audit plugins has these members:
- interface_version: By convention, type-specific plugin descriptors begin with the interface version for the given plugin type. The server checks- interface_versionwhen it loads the plugin to see whether the plugin is compatible with it. For audit plugins, the value of the- interface_versionmember is- MYSQL_AUDIT_INTERFACE_VERSION(defined in- plugin_audit.h).
- release_thd: A function that the server calls to inform the plugin that it is being dissociated from its thread context. This should be- NULLif there is no such function.
- event_notify: A function that the server calls to notify the plugin that an auditable event has occurred. This function should not be- NULL; that would not make sense because no auditing would occur.
- class_mask: An array of- MYSQL_AUDIT_CLASS_MASK_SIZEelements. Each element specifies a bitmask for a given event class to indicate the subclasses for which the plugin wants notification. (This is how the plugin “subscribes” to events of interest.) An element should be 0 to ignore all events for the corresponding event class.
            The server uses the event_notify and
            release_thd functions together. They are
            called within the context of a specific thread, and a thread
            might perform an activity that produces several event
            notifications. The first time the server calls
            event_notify for a thread, it creates a
            binding of the plugin to the thread. The plugin cannot be
            uninstalled while this binding exists. When no more events
            for the thread will occur, the server informs the plugin of
            this by calling the release_thd function,
            and then destroys the binding. For example, when a client
            issues a statement, the thread processing the statement
            might notify audit plugins about the result set produced by
            the statement and about the statement being logged. After
            these notifications occur, the server releases the plugin
            before putting the thread to sleep until the client issues
            another statement.
          
            This design enables the plugin to allocate resources needed
            for a given thread in the first call to the
            event_notify function and release them in
            the release_thd function:
          
event_notify function:
  if memory is needed to service the thread
    allocate memory
  ... rest of notification processing ...
release_thd function:
  if memory was allocated
    release memory
  ... rest of release processing ...That is more efficient than allocating and releasing memory repeatedly in the notification function.
            For the NULL_AUDIT audit plugin, the
            type-specific plugin descriptor looks like this:
          
static struct st_mysql_audit audit_null_descriptor=
{
  MYSQL_AUDIT_INTERFACE_VERSION,                    /* interface version    */
  NULL,                                             /* release_thd function */
  audit_null_notify,                                /* notify function      */
  { (unsigned long) MYSQL_AUDIT_GENERAL_ALL,
    (unsigned long) MYSQL_AUDIT_CONNECTION_ALL,
    (unsigned long) MYSQL_AUDIT_PARSE_ALL,
    (unsigned long) MYSQL_AUDIT_AUTHORIZATION_ALL,
    (unsigned long) MYSQL_AUDIT_TABLE_ACCESS_ALL,
    (unsigned long) MYSQL_AUDIT_GLOBAL_VARIABLE_ALL,
    (unsigned long) MYSQL_AUDIT_SERVER_STARTUP_ALL,
    (unsigned long) MYSQL_AUDIT_SERVER_SHUTDOWN_ALL,
    (unsigned long) MYSQL_AUDIT_COMMAND_ALL,
    (unsigned long) MYSQL_AUDIT_QUERY_ALL,
    (unsigned long) MYSQL_AUDIT_STORED_PROGRAM_ALL }
};
            The server calls audit_null_notify() to
            pass audit event information to the plugin. The plugin has
            no release_thd function.
          
            The class_mask member is an array that
            indicates which event classes the plugin subscribes to. As
            shown, the array contents subscribe to all subclasses of all
            event classes that are available. To ignore all
            notifications for a given event class, specify the
            corresponding class_mask element as 0.
          
            The number of class_mask elements
            corresponds to the number of event classes, each of which is
            listed in the mysql_event_class_t
            enumeration defined in plugin_audit.h:
          
typedef enum
{
  MYSQL_AUDIT_GENERAL_CLASS          = 0,
  MYSQL_AUDIT_CONNECTION_CLASS       = 1,
  MYSQL_AUDIT_PARSE_CLASS            = 2,
  MYSQL_AUDIT_AUTHORIZATION_CLASS    = 3,
  MYSQL_AUDIT_TABLE_ACCESS_CLASS     = 4,
  MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS  = 5,
  MYSQL_AUDIT_SERVER_STARTUP_CLASS   = 6,
  MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS  = 7,
  MYSQL_AUDIT_COMMAND_CLASS          = 8,
  MYSQL_AUDIT_QUERY_CLASS            = 9,
  MYSQL_AUDIT_STORED_PROGRAM_CLASS   = 10,
  /* This item must be last in the list. */
  MYSQL_AUDIT_CLASS_MASK_SIZE
} mysql_event_class_t;
            For any given event class,
            plugin_audit.h defines bitmask symbols
            for individual event subclasses, as well as an
            xxx_ALLMYSQL_AUDIT_CONNECTION_CLASS (the
            class that covers connect and disconnect events),
            plugin_audit.h defines these symbols:
          
typedef enum
{
  /** occurs after authentication phase is completed. */
  MYSQL_AUDIT_CONNECTION_CONNECT          = 1 << 0,
  /** occurs after connection is terminated. */
  MYSQL_AUDIT_CONNECTION_DISCONNECT       = 1 << 1,
  /** occurs after COM_CHANGE_USER RPC is completed. */
  MYSQL_AUDIT_CONNECTION_CHANGE_USER      = 1 << 2,
  /** occurs before authentication. */
  MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE = 1 << 3
} mysql_event_connection_subclass_t;
#define MYSQL_AUDIT_CONNECTION_ALL (MYSQL_AUDIT_CONNECTION_CONNECT | \
                                    MYSQL_AUDIT_CONNECTION_DISCONNECT | \
                                    MYSQL_AUDIT_CONNECTION_CHANGE_USER | \
                                    MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE)
            To subscribe to all subclasses of the connection event class
            (as the NULL_AUDIT plugin does), a plugin
            specifies MYSQL_AUDIT_CONNECTION_ALL in
            the corresponding class_mask element
            (class_mask[1] in this case). To
            subscribe to only some subclasses, the plugin sets the
            class_mask element to the union of the
            subclasses of interest. For example, to subscribe only to
            the connect and change-user subclasses, the plugin sets
            class_mask[1] to this value:
          
MYSQL_AUDIT_CONNECTION_CONNECT | MYSQL_AUDIT_CONNECTION_CHANGE_USER
            Most of the work for an audit plugin occurs in the
            notification function (the event_notify
            member of the type-specific plugin descriptor). The server
            calls this function for each auditable event. Audit plugin
            notification functions have this prototype:
          
int (*event_notify)(MYSQL_THD, mysql_event_class_t, const void *);
            The second and third parameters of the
            event_notify function prototype represent
            the event class and a generic pointer to an event structure.
            (Events in different classes have different structures. The
            notification function can use the event class value to
            determine which event structure applies.) The function
            processes the event and returns a status indicating whether
            the server should continue processing the event or terminate
            it.
          
            For NULL_AUDIT, the notification function
            is audit_null_notify(). This function
            increments a global event counter (which the plugin exposes
            as the value of the Audit_null_called
            status value), and then examines the event class to
            determine how to process the event structure:
          
static int audit_null_notify(MYSQL_THD thd __attribute__((unused)),
                             mysql_event_class_t event_class,
                             const void *event)
{
  ...
  number_of_calls++;
  if (event_class == MYSQL_AUDIT_GENERAL_CLASS)
  {
    const struct mysql_event_general *event_general=
                                    (const struct mysql_event_general *)event;
    ...
  }
  else if (event_class == MYSQL_AUDIT_CONNECTION_CLASS)
  {
    const struct mysql_event_connection *event_connection=
                                (const struct mysql_event_connection *) event;
    ...
  }
  else if (event_class == MYSQL_AUDIT_PARSE_CLASS)
  {
    const struct mysql_event_parse *event_parse =
                                      (const struct mysql_event_parse *)event;
    ...
  }
  ...
}
            The notification function interprets the
            event argument according to the value of
            event_class. The event
            argument is a generic pointer to the event record, the
            structure of which differs per event class. (The
            plugin_audit.h file contains the
            structures that define the contents of each event class.)
            For each class, audit_null_notify() casts
            the event to the appropriate class-specific structure and
            then checks its subclass to determine which subclass counter
            to increment. For example, the code to handle events in the
            connection-event class looks like this:
          
else if (event_class == MYSQL_AUDIT_CONNECTION_CLASS)
{
  const struct mysql_event_connection *event_connection=
                              (const struct mysql_event_connection *) event;
  switch (event_connection->event_subclass)
  {
  case MYSQL_AUDIT_CONNECTION_CONNECT:
    number_of_calls_connection_connect++;
    break;
  case MYSQL_AUDIT_CONNECTION_DISCONNECT:
    number_of_calls_connection_disconnect++;
    break;
  case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
    number_of_calls_connection_change_user++;
    break;
  case MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE:
    number_of_calls_connection_pre_authenticate++;
      break;
  default:
    break;
  }
}
              The general event class
              (MYSQL_AUDIT_GENERAL_CLASS) is
              deprecated and will be removed in a future MySQL release.
              To reduce plugin overhead, it is preferable to subscribe
              only to the more specific event classes of interest.
            
            For some event classes, the NULL_AUDIT
            plugin performs other processing in addition to incrementing
            a counter. In any case, when the notification function
            finishes processing the event, it should return a status
            indicating whether the server should continue processing the
            event or terminate it.
          
Audit plugin notification functions can report a status value for the current event two ways:
- Use the notification function return value. In this case, the function returns zero if the server should continue processing the event, or nonzero if the server should terminate the event. 
- 
Call the my_message()function to set the error state before returning from the notification function. In this case, the notification function return value is ignored and the server aborts the event and terminates event processing with an error. Themy_message()arguments indicate which error to report, and its message. For example:my_message(ER_AUDIT_API_ABORT, "This is my error message.", MYF(0));Some events cannot be aborted. A nonzero return value is not taken into consideration and the my_message()error call must follow anis_error()check. For example:if (!thd->get_stmt_da()->is_error()) { my_message(ER_AUDIT_API_ABORT, "This is my error message.", MYF(0)); }
These events cannot be aborted:
- MYSQL_AUDIT_CONNECTION_DISCONNECT: The server cannot prevent a client from disconnecting.
- MYSQL_AUDIT_COMMAND_END: This event provides the status of a command that has finished executing, so there is no purpose to terminating it.
            If an audit plugin returns nonzero status for a
            nonterminable event, the server ignores the status and
            continues processing the event. This is also true if an
            audit plugin uses the my_message()
            function to terminate a nonterminable event.
          
            To compile and install a plugin library file, use the
            instructions in
            Section 4.4.3, “Compiling and Installing Plugin Libraries”. To make the
            library file available for use, install it in the plugin
            directory (the directory named by the
            plugin_dir system
            variable). For the NULL_AUDIT plugin, it
            is compiled and installed when you build MySQL from source.
            It is also included in binary distributions. The build
            process produces a shared object library with a name of
            adt_null.so (the
            .so suffix might differ depending on
            your platform).
          
            To register the plugin at runtime, use this statement,
            adjusting the .so suffix for your
            platform as necessary:
          
INSTALL PLUGIN NULL_AUDIT SONAME 'adt_null.so';For additional information about plugin loading, see Installing and Uninstalling Plugins.
            To verify plugin installation, examine the
            INFORMATION_SCHEMA.PLUGINS
            table or use the SHOW PLUGINS
            statement. See
            Obtaining Server Plugin Information.
          
            While the NULL_AUDIT audit plugin is
            installed, it exposes status variables that indicate the
            events for which the plugin has been called:
          
mysql> SHOW STATUS LIKE 'Audit_null%';
+----------------------------------------+--------+
| Variable_name                          | Value  |
+----------------------------------------+--------+
| Audit_null_authorization_column        | 0      |
| Audit_null_authorization_db            | 0      |
| Audit_null_authorization_procedure     | 0      |
| Audit_null_authorization_proxy         | 0      |
| Audit_null_authorization_table         | 0      |
| Audit_null_authorization_user          | 0      |
| Audit_null_called                      | 185547 |
| Audit_null_command_end                 | 20999  |
| Audit_null_command_start               | 21001  |
| Audit_null_connection_change_user      | 0      |
| Audit_null_connection_connect          | 5823   |
| Audit_null_connection_disconnect       | 5818   |
| Audit_null_connection_pre_authenticate | 5823   |
| Audit_null_general_error               | 1      |
| Audit_null_general_log                 | 26559  |
| Audit_null_general_result              | 19922  |
| Audit_null_general_status              | 21000  |
| Audit_null_global_variable_get         | 0      |
| Audit_null_global_variable_set         | 0      |
| Audit_null_message_internal            | 0      |
| Audit_null_message_user                | 0      |
| Audit_null_parse_postparse             | 14648  |
| Audit_null_parse_preparse              | 14648  |
| Audit_null_query_nested_start          | 6      |
| Audit_null_query_nested_status_end     | 6      |
| Audit_null_query_start                 | 14648  |
| Audit_null_query_status_end            | 14647  |
| Audit_null_server_shutdown             | 0      |
| Audit_null_server_startup              | 1      |
| Audit_null_table_access_delete         | 104    |
| Audit_null_table_access_insert         | 2839   |
| Audit_null_table_access_read           | 97842  |
| Audit_null_table_access_update         | 278    |
+----------------------------------------+--------+
            Audit_null_called counts all events, and
            the other variables count instances of specific event
            subclasses. For example, the preceding
            SHOW STATUS statement causes
            the server to send a result to the client and to write a
            message to the general query log if that log is enabled.
            Thus, a client that issues the statement repeatedly causes
            Audit_null_called,
            Audit_null_general_result, and
            Audit_null_general_log to be incremented
            each time. Notifications occur whether or not that log is
            enabled.
          
The status variables values are global and aggregated across all sessions. There are no counters for individual sessions.
            NULL_AUDIT exposes several system
            variables that enable communication with the plugin at
            runtime:
          
mysql> SHOW VARIABLES LIKE 'null_audit%';
+---------------------------------------------------+-------+
| Variable_name                                     | Value |
+---------------------------------------------------+-------+
| null_audit_abort_message                          |       |
| null_audit_abort_value                            | 1     |
| null_audit_event_order_check                      |       |
| null_audit_event_order_check_consume_ignore_count | 0     |
| null_audit_event_order_check_exact                | 1     |
| null_audit_event_order_started                    | 0     |
| null_audit_event_record                           |       |
| null_audit_event_record_def                       |       |
+---------------------------------------------------+-------+
            The NULL_AUDIT system variables have
            these meanings:
          
- null_audit_abort_message: The custom error message to use when an event is aborted.
- null_audit_abort_value: The custom error code to use when an event is aborted.
- null_audit_event_order_check: Prior to event matching, the expected event order. After event matching, the matching outcome.
- null_audit_event_order_check_consume_ignore_count: Number of times event matching should not consume matched events.
- null_audit_event_order_check_exact: Whether event matching must be exact. Disabling this variable enables skipping events not listed in- null_audit_event_order_checkduring event-order matching. Of the events specified, they must still match in the order given.
- null_audit_event_order_started: For internal use.
- null_audit_event_record: The recorded events after event recording takes place.
- null_audit_event_record_def: The names of the start and end events to match when recording events, separated by a semicolon. The value must be set before each statement for which events are recorded.
            To demonstrate use of those system variables, suppose that a
            table db1.t1 exists, created as follows:
          
CREATE DATABASE db1;
CREATE TABLE db1.t1 (a VARCHAR(255));
            For test-creation purposes, it is possible to record events
            that pass through the plugin. To start recording, specify
            the start and end events in the
            null_audit_event_record_def variable. For
            example:
          
SET @@null_audit_event_record_def =
  'MYSQL_AUDIT_COMMAND_START;MYSQL_AUDIT_COMMAND_END';
            After a statement occurs that matches those start and end
            events, the null_audit_event_record
            system variable contains the resulting event sequence. For
            example, after recording the events for a SELECT
            1 statement,
            null_audit_event_record is a string that
            has a value consisting of a set of event strings:
          
MYSQL_AUDIT_COMMAND_START;command_id="3";
MYSQL_AUDIT_PARSE_PREPARSE;;
MYSQL_AUDIT_PARSE_POSTPARSE;;
MYSQL_AUDIT_GENERAL_LOG;;
MYSQL_AUDIT_QUERY_START;sql_command_id="0";
MYSQL_AUDIT_QUERY_STATUS_END;sql_command_id="0";
MYSQL_AUDIT_GENERAL_RESULT;;
MYSQL_AUDIT_GENERAL_STATUS;;
MYSQL_AUDIT_COMMAND_END;command_id="3";
            After recording the events for an INSERT INTO
            db1.t1 VALUES ('some data') statement,
            null_audit_event_record has this value:
          
MYSQL_AUDIT_COMMAND_START;command_id="3";
MYSQL_AUDIT_PARSE_PREPARSE;;
MYSQL_AUDIT_PARSE_POSTPARSE;;
MYSQL_AUDIT_GENERAL_LOG;;
MYSQL_AUDIT_QUERY_START;sql_command_id="5";
MYSQL_AUDIT_TABLE_ACCESS_INSERT;db="db1" table="t1";
MYSQL_AUDIT_QUERY_STATUS_END;sql_command_id="5";
MYSQL_AUDIT_GENERAL_RESULT;;
MYSQL_AUDIT_GENERAL_STATUS;;
MYSQL_AUDIT_COMMAND_END;command_id="3";Each event string has this format, with semicolons separating the string parts:
event_name;event_data;commandEvent strings have these parts:
- event_name: The event name (a symbol that begins with- MYSQL_AUDIT_).
- event_data: Empty, or, as described later, data associated with the event.
- command: Empty, or, as described later, a command to execute when the event is matched.
              A limitation of the NULL_AUDIT plugin
              is that event recording works for a single session only.
              Once you record events in a given session, event recording
              in subsequent sessions yields a
              null_audit_event_record value of
              NULL. To record events again, it is
              necessary to restart the plugin.
            
            To check the order of audit API calls, set the
            null_audit_event_order_check variable to
            the expected event order for a particular operation, listing
            one or more event strings, each containing two semicolons
            internally, with additional semicolons separating adjacent
            event strings:
          
event_name;event_data;command [;event_name;event_data;command] ...For example:
SET @@null_audit_event_order_check =
  'MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE;;;'
  'MYSQL_AUDIT_GENERAL_LOG;;;'
  'MYSQL_AUDIT_CONNECTION_CONNECT;;';For better readability, the statement takes advantage of the SQL syntax that concatenates adjacent strings into a single string.
            After you set the
            null_audit_event_order_check variable to
            a list of event strings, the next matching operation
            replaces the variable value with a value that indicates the
            operation outcome:
          
- If the expected event order was matched successfully, the resulting - null_audit_event_order_checkvalue is- EVENT-ORDER-OK.
- If the - null_audit_event_order_checkvalue specified aborting a matched event (as described later), the resulting- null_audit_event_order_checkvalue is- EVENT-ORDER-ABORT.
- If the expected event order failed with unexpected data, the resulting - null_audit_event_order_checkvalue is- EVENT-ORDER-INVALID-DATA. This occurs, for example, if an event was specified as expected to affect table- t1but actually affected- t2.
            When you assign to
            null_audit_event_order_check the list of
            events to be matched, some events should be specified with a
            nonempty event_data part of the
            event string. The following table shows the
            event_data format for these
            events. If an event takes multiple data values, they must be
            specified in the order shown. Alternatively, it is possible
            to specify an event_data value as
            <IGNORE> to ignore event data
            content; in this case, it does not matter whether or not an
            event haas data.
          
| Applicable Events | Event Data Format | 
|---|---|
| 
                     
                     | command_id=" | 
| 
                     
                     | name=" | 
| 
                     
                     
                     
                     | sql_command_id=" | 
| 
                     
                     
                     
                     | db=" | 
            In the null_audit_event_order_check
            value, specifying ABORT_RET in the
            command part of an event string
            makes it possible to abort the audit API call on the
            specified event. (Assuming that the event is one that can be
            aborted. Those that cannot were described previously.) For
            example, as shown previously, this is the expected order of
            events for an insert into t1:
          
MYSQL_AUDIT_COMMAND_START;command_id="3";
MYSQL_AUDIT_PARSE_PREPARSE;;
MYSQL_AUDIT_PARSE_POSTPARSE;;
MYSQL_AUDIT_GENERAL_LOG;;
MYSQL_AUDIT_QUERY_START;sql_command_id="5";
MYSQL_AUDIT_TABLE_ACCESS_INSERT;db="db1" table="t1";
MYSQL_AUDIT_QUERY_STATUS_END;sql_command_id="5";
MYSQL_AUDIT_GENERAL_RESULT;;
MYSQL_AUDIT_GENERAL_STATUS;;
MYSQL_AUDIT_COMMAND_END;command_id="3";
            To abort INSERT statement
            execution when the
            MYSQL_AUDIT_QUERY_STATUS_END event
            occurs, set null_audit_event_order_check
            like this (remember to add semicolon separators between
            adjacent event strings):
          
SET @@null_audit_event_order_check =
  'MYSQL_AUDIT_COMMAND_START;command_id="3";;'
  'MYSQL_AUDIT_PARSE_PREPARSE;;;'
  'MYSQL_AUDIT_PARSE_POSTPARSE;;;'
  'MYSQL_AUDIT_GENERAL_LOG;;;'
  'MYSQL_AUDIT_QUERY_START;sql_command_id="5";;'
  'MYSQL_AUDIT_TABLE_ACCESS_INSERT;db="db1" table="t1";;'
  'MYSQL_AUDIT_QUERY_STATUS_END;sql_command_id="5";ABORT_RET';
            It is not necesary to list events that are expected to occur
            after the event string that contains a
            command value of
            ABORT_RET.
          
            After the audit plugin matches the preceding sequence, it
            aborts event processing and sends an error message to the
            client. It also sets
            null_audit_event_order_check to
            EVENT-ORDER-ABORT:
          
mysql> INSERT INTO db1.t1 VALUES ('some data');
ERROR 3164 (HY000): Aborted by Audit API ('MYSQL_AUDIT_QUERY_STATUS_END';1).
mysql> SELECT @@null_audit_event_order_check;
+--------------------------------+
| @@null_audit_event_order_check |
+--------------------------------+
| EVENT-ORDER-ABORT              |
+--------------------------------+
            Returning a nonzero value from the audit API notification
            routine is the standard way to abort event execution. It is
            also possible to specify a custom error code by setting the
            null_audit_abort_value variable to the
            value that the notification routine should return:
          
SET @@null_audit_abort_value = 123;
            Aborting a sequence results in a standard message with the
            custom error code. Suppose that you set audit log system
            variables like this, to abort on a match for the events that
            occur for a SELECT 1 statement:
          
SET @@null_audit_abort_value = 123;
SET @@null_audit_event_order_check =
  'MYSQL_AUDIT_COMMAND_START;command_id="3";;'
  'MYSQL_AUDIT_PARSE_PREPARSE;;;'
  'MYSQL_AUDIT_PARSE_POSTPARSE;;;'
  'MYSQL_AUDIT_GENERAL_LOG;;;'
  'MYSQL_AUDIT_QUERY_START;sql_command_id="0";ABORT_RET';
            Then execution of SELECT 1 results in
            this error message that includes the custom error code:
          
mysql> SELECT 1;
ERROR 3164 (HY000): Aborted by Audit API ('MYSQL_AUDIT_QUERY_START';123).
mysql> SELECT @@null_audit_event_order_check;
+--------------------------------+
| @@null_audit_event_order_check |
+--------------------------------+
| EVENT-ORDER-ABORT              |
+--------------------------------+
            An event can be also aborted with a custom message,
            specified by setting the
            null_audit_abort_message variable.
            Suppose that you set audit log system variables like this:
          
SET @@null_audit_abort_message = 'Custom error text.';
SET @@null_audit_event_order_check =
  'MYSQL_AUDIT_COMMAND_START;command_id="3";;'
  'MYSQL_AUDIT_PARSE_PREPARSE;;;'
  'MYSQL_AUDIT_PARSE_POSTPARSE;;;'
  'MYSQL_AUDIT_GENERAL_LOG;;;'
  'MYSQL_AUDIT_QUERY_START;sql_command_id="0";ABORT_RET';Then aborting a sequence results in the following error message:
mysql> SELECT 1;
ERROR 3164 (HY000): Custom error text.
mysql> SELECT @@null_audit_event_order_check;
+--------------------------------+
| @@null_audit_event_order_check |
+--------------------------------+
| EVENT-ORDER-ABORT              |
+--------------------------------+
            To disable the NULL_AUDIT plugin after
            testing it, use this statement to unload it:
          
UNINSTALL PLUGIN NULL_AUDIT;