PolarDB MySQL版提供的SQL Detail功能,用于对库表变更和加锁操作做详细审计,并对审计记录做自动淘汰管理。

背景信息

在使用数据库的过程中,库表的变更(如创建列和索引、增加列和索引以及删除列和索引)或对库表加锁等操作会影响业务的正常使用,对应操作的审计日志对数据库的运维人员至关重要,运维人员需要知道对应操作的用户账号、客户端IP地址、操作时间以及完成时间等详细信息。

在此之前,审计日志基本都是全局开关,即对所有的SQL语句做审计,虽然记录的审计日志很全面,但成本相对较高。甚至有时会需要额外的组件来存储信息。

PolarDB MySQL版提供了SQL Detail功能,能够对库表变更和加锁操作做详细审计。该功能在相关语句开始执行时就捕获到相关记录,并将审计记录存储在数据库的系统表中。您可以根据业务需要配置审计记录的保存时间,超过该时间的审计记录将会被自动淘汰。且该功能的审计成本极低,以单条审计记录的存储容量为1 KB,单日库表变更1024次,审计记录保存时间为30天计算,仅需要30 MB的存储空间。

前提条件

PolarDB集群版本需满足如下条件之一:
  • PolarDB MySQL版8.0.1版本且修订版本为8.0.1.1.31及以上。
  • PolarDB MySQL版8.0.2版本且修订版本为8.0.2.2.12及以上。
您可以通过查询版本号来确认集群版本。

参数说明

您可以在控制台上设置以下参数,来开启SQL Detail功能以及设置审计记录的保存时间。设置参数操作步骤请参见设置集群参数和节点参数
参数级别说明
loose_awr_sqldetail_enabledGlobal开启或关闭SQL Detail功能。取值如下:
  • OFF(默认):关闭SQL Detail功能。
  • ON:开启SQL Detail功能。
loose_awr_sqldetail_switchGlobalSQL Detail记录的操作类型。子开关如下:
  • ddl:记录DDL操作。取值如下:
    • ON(默认):记录DDL操作的详细信息。
    • OFF:不记录DDL操作的详细信息。
  • lock_db_table:记录LOCK DB、LOCK TABLE操作。取值如下:
    • ON(默认):记录LOCK DB、LOCK TABLE操作的详细信息。
    • OFF:不记录LOCK DB、LOCK TABLE操作的详细信息。
loose_awr_sqldetail_retentionGlobal审计记录的保存时间。超过该时间的记录会被自动淘汰。

取值范围:0~18446744073709551615。默认值为2592000。单位:秒。

表结构说明

PolarDB MySQL版内置了一张系统表sys.hist_sqldetail,用于保存审计记录。系统启动时会自动创建该表,无需您手动创建。该系统表的表结构如下:
CREATE TABLE `hist_sqldetail` (
  `Id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `State` varchar(16) COLLATE utf8mb4_bin DEFAULT NULL,
  `Thread_id` bigint(20) unsigned DEFAULT NULL,
  `Host` varchar(60) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
  `User` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
  `Client_ip` varchar(60) COLLATE utf8mb4_bin DEFAULT NULL,
  `Db` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL,
  `Sql_text` mediumtext COLLATE utf8mb4_bin NOT NULL,
  `Server_command` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL,
  `Sql_command` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL,
  `Start_time` timestamp(6) NULL DEFAULT NULL,
  `Exec_time` bigint(20) DEFAULT NULL,
  `Wait_time` bigint(20) DEFAULT NULL,
  `Error_code` int(11) DEFAULT NULL,
  `Rows_sent` bigint(20) DEFAULT NULL,
  `Rows_examined` bigint(20) DEFAULT NULL,
  `Rows_affected` bigint(20) DEFAULT NULL,
  `Logical_read` bigint(20) DEFAULT NULL,
  `Phy_sync_read` bigint(20) DEFAULT NULL,
  `Phy_async_read` bigint(20) DEFAULT NULL,
  `Process_info` text COLLATE utf8mb4_bin,
  `Extra` text COLLATE utf8mb4_bin,
  `Create_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
  `Update_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
  PRIMARY KEY (`Id`),
  KEY `i_start_time` (`Start_time`),
  KEY `i_update_time` (`Update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
系统表中的参数说明如下:
参数说明
Id自增ID。
State该操作被记录时所处的状态。
Thread_id执行该SQL语句的线程ID。
Host执行该SQL语句的用户。
User执行该SQL语句的用户名。
Client_ip执行该SQL语句的客户端IP地址。
Db执行该SQL语句的数据库名称。
Sql_text执行的SQL语句。
Server_command执行该SQL语句的Server命令。
Sql_commandSQL语句的命令类型。
Start_time开始执行SQL语句的时间。
Exec_time执行耗时。单位:微秒。
Wait_time等待时间。单位:微秒。
Error_code错误码。
Rows_sent返回的数据行数。
Rows_examined扫描的数据行数。
Rows_affected影响的行数。
Logical_read逻辑读次数。
Phy_sync_read物理同步读次数。
Phy_async_read物理异步读次数。
Process_info扩展字段,处理过程信息。
Extra扩展字段,其他信息。
Create_time记录写入时间。
Update_time记录更新时间。

示例

  1. 在控制台将参数loose_awr_sqldetail_enabled设置为ON,并在数据库中执行以下命令。
    create table t(c1 int);
    Query OK, 0 rows affected (0.02 sec)
    
    create table t(c1 int);
    ERROR 1050 (42S01): Table 't' already exists
    
    alter table t add column c2 int;
    Query OK, 0 rows affected (0.02 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    lock tables t read;
    Query OK, 0 rows affected (0.00 sec)
    
    unlock tables;
    Query OK, 0 rows affected (0.00 sec)
    
    insert into t values(1, 2);
    Query OK, 1 row affected (0.00 sec)
  2. 执行以下命令,查看sys.hist_sqldetail表中记录的审计信息。
    select * from sys.hist_sqldetail\G
    执行结果如下:
    *************************** 1. row ***************************
                Id: 1
             State: FINISH
         Thread_id: 18
              Host: localhost
              User: root
         Client_ip: 127.0.0.1
                Db: test
          Sql_text: create table t(c1 int)
    Server_command: Query
       Sql_command: create_table
        Start_time: 2023-01-13 16:18:21.840435
         Exec_time: 17390
         Wait_time: 318
        Error_code: 0
         Rows_sent: 0
     Rows_examined: 0
     Rows_affected: 0
      Logical_read: 420
     Phy_sync_read: 0
    Phy_async_read: 0
      Process_info: NULL
             Extra: NULL
       Create_time: 2023-01-13 16:18:22.391407
       Update_time: 2023-01-13 16:18:22.391407
    *************************** 2. row ***************************
                Id: 2
             State: FINISH
         Thread_id: 18
              Host: localhost
              User: root
         Client_ip: 127.0.0.1
                Db: test
          Sql_text: create table t(c1 int)
    Server_command: Query
       Sql_command: create_table
        Start_time: 2023-01-13 16:18:22.416321
         Exec_time: 822
         Wait_time: 229
        Error_code: 1050
         Rows_sent: 0
     Rows_examined: 0
     Rows_affected: 0
      Logical_read: 55
     Phy_sync_read: 0
    Phy_async_read: 0
      Process_info: NULL
             Extra: NULL
       Create_time: 2023-01-13 16:18:23.393071
       Update_time: 2023-01-13 16:18:23.393071
    *************************** 3. row ***************************
                Id: 3
             State: FINISH
         Thread_id: 18
              Host: localhost
              User: root
         Client_ip: 127.0.0.1
                Db: test
          Sql_text: alter table t add column c2 int
    Server_command: Query
       Sql_command: alter_table
        Start_time: 2023-01-13 16:18:34.123947
         Exec_time: 16420
         Wait_time: 245
        Error_code: 0
         Rows_sent: 0
     Rows_examined: 0
     Rows_affected: 0
      Logical_read: 778
     Phy_sync_read: 0
    Phy_async_read: 0
      Process_info: NULL
             Extra: NULL
       Create_time: 2023-01-13 16:18:34.394067
       Update_time: 2023-01-13 16:18:34.394067
    *************************** 4. row ***************************
                Id: 4
             State: FINISH
         Thread_id: 18
              Host: localhost
              User: root
         Client_ip: 127.0.0.1
                Db: test
          Sql_text: lock tables t read
    Server_command: Query
       Sql_command: lock_tables
        Start_time: 2023-01-13 16:19:49.891559
         Exec_time: 145
         Wait_time: 129
        Error_code: 0
         Rows_sent: 0
     Rows_examined: 0
     Rows_affected: 0
      Logical_read: 0
     Phy_sync_read: 0
    Phy_async_read: 0
      Process_info: NULL
             Extra: NULL
       Create_time: 2023-01-13 16:19:50.399585
       Update_time: 2023-01-13 16:19:50.399585
    *************************** 5. row ***************************
                Id: 5
             State: FINISH
         Thread_id: 18
              Host: localhost
              User: root
         Client_ip: 127.0.0.1
                Db: test
          Sql_text: unlock tables
    Server_command: Query
       Sql_command: unlock_tables
        Start_time: 2023-01-13 16:19:56.924648
         Exec_time: 98
         Wait_time: 0
        Error_code: 0
         Rows_sent: 0
     Rows_examined: 0
     Rows_affected: 0
      Logical_read: 0
     Phy_sync_read: 0
    Phy_async_read: 0
      Process_info: NULL
             Extra: NULL
       Create_time: 2023-01-13 16:19:57.400294
       Update_time: 2023-01-13 16:19:57.400294
    从上述查询结果可以看出,SQL Detail功能只记录DDL、LOCK DB和LOCKTABLE的审计信息,而不记录DML操作的审计信息。且SQL Detail功能在SQL语句开始执行时,就将捕获到的信息记录到系统表中,当该SQL语句执行完成后,会自动更新系统表中的状态等信息。