Mycat的SQL拦截功能

为何需要使用Mycat的SQL拦截功能? 首先,我们来列举一个真实的案例场景:我们在实际的工作中,经常会遇到这样一种场景:业务人员突然发现业务数据库中的数据被莫名其妙的修改了,但又不知道是如何修改的。于是,就来求助DBA,想要来查询一下修改数据的SQL语句。通常情况下,DBA只能通过分析binlog的方式来查找修改数据的SQL语句。如果使用的binlog格式是row格式,那么,在binlog中是根本不会记录修改数据的原始SQL语句的。因此,在binlog日志中所获得的SQL语句,无法帮助业务人员来分析问题。

那么,有什么办法能够记录业务系统发送到数据库的实际的SQL语句吗?答案是:有。使用Mycat的SQL拦截功能就能够实现这样的要求。

当然,我们也可以使用MySQL本身提供的slow_log和general_log来记录业务系统发送给数据库的实际SQL语句,但是这两种日志会将所有发送给数据库的SQL语句记录下来,其中,也会包含大量的salve语句。而在实际工作过程中,大部分场景下我们只需要记录update语句即可。由于使用MySQL本身提供的slow_log和general_log无法做到灵活的配置处理,所以,在实际工作中,基本不会使用MySQL本身提供的slow_log和general_log来记录相应的SQL语句。

Mycat提供的SQL拦截功能,允许自定义拦截SQL语句的类型。例如,使用Mycat的SQL拦截功能能够实现只监控数据库的写入操作。

另外,如果需要对用户写的SQL语句进行审计,也需要将用户写的SQL语句通过日志记录下来,这也是SQL拦截功能的另一个使用场景。

当然,记录全部的用户请求所触发的SQL语句,我们也可以使用MySQL本身提供的slow_log和general_log。不过,当我们使用Mycat对后端数据库进行切分之后,使用MySQL本身提供的slow_log和general_log会分别存储在多个数据节点中,查询起来会及其不方便。

而Mycat的SQL拦截功能可以将这些SQL语句统一放到同一个日志文件中,这就为我们后续分析SQL语句提供了很大的便利。

如何配置Mycat的SQL拦截功能? 配置Mycat的SQL拦截功能需要在server.xml文件中的system标签中增加几个属性的配置。如下所示。

<system>
    <property name="sqlInterceptor">
        io.mycat.server.interceptor.impl.StatisticsSqlInterceptor
    </property>
    <property name="sqlInterceptorType">
        UPDATE,DELETE,INSERT
    </property>
    <property name="sqlInterceptorFile">/tmp/sql.txt</property>
</system>

上述配置项理解起来也比较简单,我就不一一说明了。需要注意的是:无论SQL语句是否执行成功,都会被Mycat拦截下来,并记录到日志中。

实际配置

接下来,我们就在Mycat的server.xml文件中增加上述配置。最终,server.xml文件的内容如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
	<system>
		<property name="useHandshakeV10">1</property>
        <property name="defaultSqlParser">druidparser</property>
		<property name="serverPort">3307</property>
		<property name="managerPort">3308</property>
		<property name="nonePasswordLogin">0</property>
		<property name="bindIp">0.0.0.0</property>
		<property name="charset">utf8mb4</property>
		<property name="frontWriteQueueSize">2048</property>
		<property name="txIsolation">2</property>
		<property name="processors">2</property>
		<property name="idleTimeout">1800000</property>
		<property name="sqlExecuteTimeout">300</property>
		<property name="useSqlStat">0</property>
		<property name="useGlobleTableCheck">0</property>
		<property name="sequenceHandlerType">1</property>
		<property name="defaultMaxLimit">1000</property>
		<property name="maxPacketSize">104857600</property>
		
		<property name="sqlInterceptor">
			io.mycat.server.interceptor.impl.StatisticsSqlInterceptor
		</property>
		<property name="sqlInterceptorType">
			UPDATE,DELETE,INSERT
		</property>
		<property name="sqlInterceptorFile">/tmp/sql.txt</property>
	</system>
	
	<user name="sulwan" defaultAccount="true">
		<property name="password">123456</property>
		<property name="schemas">shop</property>
	</user>
  
</mycat:server>

至此,Mycat的SQL拦截功能配置完成。