其实,看到这个标题后,我本人也会提出一个疑问: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="mycat" defaultAccount="true">
<property name="usingDecrypt">1</property>
<property name="password">cTwf23RrpBCEmalp/nx0BAKenNhvNs2NSr9nYiMzHADeEDEfwVWlI6hBDccJjNBJqJxnunHFp5ae63PPnMfGYA==</property>
<property name="schemas">shop</property>
</user>
</mycat:server>
至此,Mycat的SQL拦截功能配置完成。