https://blog.csdn.net/fanxiaobin577328725/article/details/71601760

一、简介

  P6Spy is a framework that enables database data to be seamlessly(无缝地) intercepted(截获) and logged with no code changes to existing application. The P6Spy distribution includes P6Log, an application which logs all JDBC transactions for any Java application.

  P6Spy 是针对数据库访问操作的动态监测框架(开源项目)它使得数据库数据可无缝截取和操纵,而不必对现有应用程序的代码作任何修改。P6Spy 分发包包括P6Log,它是一 个可记录任何 Java 应用程序的所有JDBC事务的应用程序。其配置完成使用时,可以进行数据访问性能的监测。
  我们最需要的功能,查看sql语句,不是预编译的带问号的,而是真正的数据库执行的sql,更直观,更简单。

  P6Spy是一个可以用来在应用程序中拦截和修改数据操作语句的开源框架。 通过P6Spy我们可以对SQL语句进行拦截,相当于一个SQL语句的记录器,这样我们可以用它来作相关的分析,比如性能分析。
P6SPY提供了如下几个功能:

  • 记录SQL语句的执行时间戳。
  • 记录SQL语句类型
  • 记录SQL填入参数的和没有填入参数的SQL语句
  • 根据配置的时间控制SQL语句的执行时间,对超出时间的SQL语句输出到日志文件中

  p6spy.(zip/tar.gz) - This is our distribution artifact containing everything that you need to use P6Spy. you would normally download this artifact if you are installing without any code changes.
  p6spy.(zip/tar.gz) -这个文件包含了你使用P6Spy所需要的任何文件。
  p6spy.jar - This is the primary artifact for p6spy. If you are integrating p6spy into your application, this is the only artifact that you need.
  p6spy.jar - 这个文件是p6spy的核心文件,如果你要将p6spy集成到你的应用中,你只需要这一个文件就可以了。(当然还需要一个spy.properties配置文件,我的理解就是依赖文件只需要此jar包即可)

注意:以上两个文件在Maven仓库中已经存在,所以可以直接从Maven仓库中获取到。

Maven的POM配置:

  1.  
    <!-- https://mvnrepository.com/artifact/p6spy/p6spy -->
  2.  
    <dependency>
  3.  
    <groupId>p6spy</groupId>
  4.  
    <artifactId>p6spy</artifactId>
  5.  
    <version>3.0.0</version>
  6.  
    </dependency>

二、实战

<1> 下载p6spy-3.0.0.zip文件,下载地址为:http://download.csdn.net/detail/fanxiaobin577328725/9839358

<2> 配置Maven依赖,如果不使用Maven可以直接将p6spy-3.0.0.zip文件中的p6spy.jar添加到lib目录中,然后Build Path -> Add To Buil Path

<3> 添加spy.properties到项目src的根目录下,该文件在p6spy-3.0.0.zip文件中

<4> 在spy.properties文件中配置真正的JDBC驱动的类名称

driverlist=com.mysql.jdbc.Driver

<5> 修改真实的JDBC的URL和驱动类,如下:

  1.  
    driverClassName="com.p6spy.engine.spy.P6SpyDriver"
  2.  
    url="jdbc:p6spy:mysql://<hostname>:<port>/<database>"

<6> 配置SQL的输出路径(以输出到控制台为例),在spy.properties文件中将appender=com.p6spy.engine.spy.appender.StdoutLogger前面的井号(#)去掉

<7> 正常运行程序,然后就可以看到预期的SQL语句了

三、配置文件详解

3.1 driverlist

  This is a comma separated list of JDBC driver classes to load and register with DriverManager. You should list the classname(s) of the JDBC driver(s) that you want to proxy with P6Spy if any of the following conditions are met.

  这个属性配置的是加载和注册DriverManager的真实的JDBC驱动类。你需要在此列出你想让P6Spy 代理的JDBC驱动的类名,而且JDBC驱动必须满足如下两个条件中任意一个。(有疑问)

  1. The JDBC driver does not implement the JDBC 4.0 API
  2. You are using a JNDI Data Source - Some application servers will prevent the automatic registration feature from working.

3.2 autoflush

  For standard development, set the autoflush value to true. When set to true, every time a statement is intercepted(拦截), it is immediately(立即) written to the log file. In some cases,however, instant feedback(反应) on every statement is not a requirement.In those cases, the system performs(执行) slightly(稍微) faster with autoflush set to false.

3.3 dateformat

  Setting a value for dateformat changes the date format value printed in the log file. No value prints the current time in milliseconds (unix time), a useful feature for parsing the log. The date format engine is Java’s SimpleDateFormat class. Refer to the SimpleDateFormat class in the JavaDocs for information on setting this value. An example follows:

dateformat=MM-dd-yy HH:mm:ss:SS

注意:如果没有指定此属性,则默认输出的是时间戳,也就是显示最前面的那一串数字字符串。对时间戳不了解的可以参考:《时间戳

3.4 stacktrace

  If stacktrace is set, the log prints out the stack trace for each SQL statement logged.

3.5 stacktraceclass

  Limits the stack traces printed to those that contain the value set in stacktraceclass. For example, specifying stacktraceclass=com.mycompany.myclass limits the printing of stack traces to the specified class value. The stack trace is converted to a String and string.indexOf(stacktraceclass) is performed.

3.6 reloadproperties and reloadpropertiesinterval

  If reloadproperties is set to true, the property file is reloaded every n seconds, where n is defined by the value set by reloadpropertiesinterval. For example, if reloadproperties=true and reloadpropertiesinterval=10, the system checks the File.lastModified() property of the property file every 10 seconds, and if the file has been modified, it will be reloaded.
  If you set append=true, the log will be suddenly truncated when you change your properties. This is because using reloadproperties is intended to be the equivalent of restarting your application server. Restarting your application server truncates your log file.
  reloadproperties will not reload any driver information (such as realdriver, realdriver2, and realdriver3) and will not change the modules that are in memory.

3.7 appender

  Appenders allow you to specify(指定) where and how log information is output. Appenders are a flexible(灵活的) architecture(结构) allowing anyone to write their own output class for P6Spy. To use an appender, specify the classname of the appender to use. The current release comes with three options which are slf4j, stdout, and logging to a file (default). Please note, that all of these output in the CSV format (where separator is: “|”).

<1> Using the File output: Uncomment(取消注释)  the FileLogger appender and specify a logfile and whether or not to append to the file or to clear the file each time:

  1.  
    #appender=com.p6spy.engine.spy.appender.Slf4JLogger
  2.  
    #appender=com.p6spy.engine.spy.appender.StdoutLogger
  3.  
    appender=com.p6spy.engine.spy.appender.FileLogger
  4.  
    # name of logfile to use, note Windows users should make sure to use forward slashes in their pathname (e:/test/spy.log)
  5.  
    # (used for com.p6spy.engine.spy.appender.FileLogger only)
  6.  
    # (default is spy.log)
  7.  
    #logfile = spy.log
  8.  
    # append to the p6spy log file. if this is set to false the
  9.  
    # log file is

注意:文件的默认保存路径是项目的根目录下,与src是平级的。
<2> Using StdOut: Uncomment the StdoutLogger as follows:

  1.  
    #appender=com.p6spy.engine.spy.appender.Slf4JLogger
  2.  
    appender=com.p6spy.engine.spy.appender.StdoutLogger
  3.  
    #appender=com.p6spy.engine.spy.appender.FileLogger

<3> Using SLF4J: Uncomment the Slf4JLogger as follows:

  1.  
    appender=com.p6spy.engine.spy.appender.Slf4JLogger
  2.  
    #appender=com.p6spy.engine.spy.appender.StdoutLogger
  3.  
    #appender=com.p6spy.engine.spy.appender.FileLogger

  In general you need to slf4j-api and the appropriate bridge to the actual logging implementation as well as the logging implementation itself on your classpath. To simplify setup for those not having any of the additional dependencies already on classpath following *-nodep.jar bundles are provided as part of p6spy distribution:

  • p6spy-<version>-log4j-nodep.jar - having log4j included
  • p6spy-<version>-log4j2-nodep.jar - having log4j2 included and
  • p6spy-<version>-logback-nodep.jar - having logback included.

Mapping to SLF4J levels is provided in the following way:
  Internally is Slf4j Logger is retrieved for the: p6spy, keep this in mind when configuring your logging implementation.So for example for the log4j following could be used to restrict the p6spy logging (if using xml-based configuration) to INFO level only:

  1.  
    <category name="p6spy">
  2.  
    <priority value="INFO" />
  3.  
    </category>

For further instructions on configuring SLF4J, see the SLF4J documentation

3.8 logMessageFormat

  The log message format is selected by specifying(指定的) the class to use to format the log messages. The following classes are available with P6Spy.

com.p6spy.engine.spy.appender.SingleLineFormat which results in log messages in format:

current time|execution time|category|connection id|statement SQL String|effective SQL string

解析:当前时间(默认是时间戳)|执行时间|执行的操作类型|connection id|statement SQL String|真实执行的SQL字符串

注意:你可能在看控制台输出的时候发现还是有问号呢?其实你看的是statement SQL String,再往后才是真实执行的SQL。

com.p6spy.engine.spy.appender.MultiLineFormat, which results in log messages in format:

  1.  
    current time|execution time|category|connection id|statement SQL String
  2.  
    effective SQL string

解析:这种格式从大体上与上面没什么区别,只是显示的细节上有所不同,首先其行首会出现一个井号(#),执行时间前面会有一个took,并带有ms单位,而且其真实执行的SQL会换行进行显示,这一点也是我想要的。总的来说,我偏向喜欢这种格式,更加清晰明了。

  • current time - the current time is obtained through System.getCurrentTimeMillis() and represents the number of milliseconds that have passed since January 1, 1970 00:00:00.000 GMT. (Refer to the J2SE documentation for further details on System.getCurrentTimeMillis().) To change the format, use the dateformat property described in Common Property File Settings.
  • execution time - the time it takes in milliseconds for a particular method to execute. (This is not the total cost for the SQL statement.) For example, a statement SELECT * FROM MYTABLE WHERE THISCOL =? might be executed as a prepared statement, in which the .execute() function will be measured. This is recorded as the statement category. Further, as you call .next() on the ResultSet, each .next() call is recorded in the result category.
  • category - You can manage your log by including and excluding categories, which is described in Common Property File Settings.
  • connection id - Indicates the connection on which the activity was logged. The connection id is a sequentially generated identifier.
  • statement SQL string - This is the SQL string passed to the statement object. If it is a prepared statement,it is the prepared statement that existed prior to the parameters being set. To see the complete statement,refer to effective SQL string.
  • effective SQL string - If you are not using a prepared statement, this contains no value. Otherwise,it fills in the values of the Prepared Statement so you can see the effective SQL statement that is passed to the database. Of course, the database still sees the prepared statement, but this string is a convenient way to see the actual values being sent to the database.

  The com.p6spy.engine.spy.appender.MultiLineFormat might be better from a readability perspective.Because it will place the effective SQL statement on a separate line. However, the SingleLineFormat might be better if you have a need to parse the log messages. The default is com.p6spy.engine.spy.appender.SingleLineFormat for backward compatibility.

  You can also supply your own log message formatter to customize the format. Simply create a class which implements the com.p6spy.engine.spy.appender.MessageFormattingStrategy interface and place it on the classpath.

3.9 filter, include, exclude

  P6Spy allows you to filter SQL queries by specific strings to be present (includes property value) or not present (excludes property value). As a precondition, setting filter=true has to be provided. P6Spy will perform string matching on each statement to determine if it should be written to the log file. include accepts a comma-delimited
list of expressions which is required to appear in a statement before it can appear in the log. exclude accepts a comma-delimited list to exclude. Exclusion overrides inclusion, so that a statement matching both an include string and an exclude string is excluded.

Please note that matching mode used in the underlying regex is (achieved via prefix (?mis)):

  An example showing capture of all statements having select, except those having order follow:

  1.  
    filter = true
  2.  
    # comma separated list of strings to include
  3.  
    include = select
  4.  
    # comma separated list of strings to exclude
  5.  
    exclude = order

Please note, that internally following regex would be used for particular expression matching: (?mis)^(?!.*(order).*)(.*(select).*)$
  An example showing only capture statements having any of: order_details, price, and price_history follows:

  1.  
    filter = true
  2.  
    # comma separated list of strings to include
  3.  
    include = order,order_details,price,price_history
  4.  
    # comma separated list of strings to exclude
  5.  
    exclude =

Please note, that internally following regex would be used for particular expression matching: (?mis)^(.*(order|order_details|price|price_history).*)$
  An example showing the capture of all statements, except statements order string in them follows:

  1.  
    filter = false
  2.  
    # comma separated list of strings to include
  3.  
    include =
  4.  
    # comma separated list of strings to exclude
  5.  
    exclude = order

Please note, that internally following regex would be used for particular expression matching: (?mis)^(?!.*(order).*)(.*)$
  As you can use full regex syntax, capture of statements having: pri[cz]e follows:

  1.  
    filter = true
  2.  
    # comma separated list of strings to include
  3.  
    include = pri[cz]e
  4.  
    # comma separated list of strings to exclude
  5.  
    exclude =

Please note, that internally following regex would be used for particular expression matching: (?mis)^(.*(pri[cz]e).*)$
  Moreover, please note, that special characters escaping (used in java) has to be done for the provided regular expression.As an example, matching for:

from\scustomers

  would mean, that following should be specified (please note doubled backslash):

  1.  
    filter=true
  2.  
    include=from\\scustomers

3.10 filter, sqlexpression

  If you need more control over regular expression for matching, SQL string property sqlexpression is to be used as an alternative to exclude and include. An example follows:

  1.  
    filter = true
  2.  
    sqlexpression = your expression

  If your expression matches the SQL string, it is logged. If the expression does not match, it is not logged. Please note you can use sqlexpression together with include/exclude, where both would be evaluated.
  Moreover, please note, that special characters escaping (used in java) has to be done for the provided regular expression.As an example, matching for:

^(.*(from\scustomers).*)$

  would mean, that following should be specified (please note doubled backslash):

  1.  
    filter=true
  2.  
    sqlexpression=^(.*(from\\scustomers).*)$

3.11 excludecategories

  The log includes category information that describes the type of statement. This property excludes the listed categories.Valid options include the following:

  • error includes P6Spy errors. (It is recommended that you include this category.)
  • info includes driver startup information and property file information.
  • debug is only intended for use when you cannot get your driver to work properly, because it writes everything.
  • statement includes Statements, PreparedStatements, and CallableStatements.
  • batch includes calls made to the addBatch() JDBC API.
  • commit includes calls made to the commit() JDBC API.
  • rollback includes calls made to the rollback() JDBC API.
  • result includes statements generated by ResultSet.

  Enter a comma-delimited list of categories to exclude from your log file. See filter, include, exclude for more details on how this process works.

3.12 outagedetection

  This feature detects long-running statements that may be indicative of a database outage problem. When enabled, it logs any statement that surpasses the configurable time boundary during its execution. No other statements are logged except the long-running statements.

3.13 outagedetectioninterval

  The interval property is the boundary time set in seconds. For example, if set to 2, any statement requiring at least 2 seconds is logged. The same statement will continue to be logged for as long as it executes. So, if the interval is set to 2 and a query takes 11 seconds, it is logged 5 times (at the 2, 4, 6, 8, 10-second intervals).

3.14 jmxPrefix

  If set to true, the execution time will be measured in nanoseconds as opposed to milliseconds.
参考资料:

【转载】 利用p6spy拦截并查看数据库执行操作的更多相关文章

  1. eclipse利用sql语句对Oracle数据库进行操作

    对Oracle数据库执行操作的sql语句中表名和列名都需用英文双引号("")括起来. 注(\为转义符) 1.插入数据 sql = "insert into \" ...

  2. 玩转SpringBoot之整合Mybatis拦截器对数据库水平分表

    利用Mybatis拦截器对数据库水平分表 需求描述 当数据量比较多时,放在一个表中的时候会影响查询效率:或者数据的时效性只是当月有效的时候:这时我们就会涉及到数据库的分表操作了.当然,你也可以使用比较 ...

  3. C# winform窗体设计-对数据库执行增删改操作

    对于学习数据库的人来说,数据库的增删改可谓是最基本的了(小编其实也只是一个小白=-=),这篇文章,小编将于大家讲解数据库增删改操作 在执行数据库增删改的时候主要使用的:Command 类       ...

  4. Django框架之ORM(数据库)操作

    一.ORM介绍 映射关系: 表名 -------------------->类名 字段-------------------->属性 表记录----------------->类实例 ...

  5. django系列5.1--ORM对数据库的操作

    Django---ORM数据库操作(图书管理系统基本实例) 一.基本知识 MVC模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Mo ...

  6. JDBC连接数据库及其执行操作

    作者:Alvin 功能:数据库连接与实现增删改查 时间:2019年3月4日08点33分 参考文章:https://www.2cto.com/database/201805/743741.html 一. ...

  7. MYSQL启用日志,查看日志,利用mysqlbinlog工具恢复MySQL数据库【转载】

    转自 MYSQL启用日志,查看日志,利用mysqlbinlog工具恢复MySQL数据库 - _安静 - 博客园http://www.cnblogs.com/xionghui/archive/2012/ ...

  8. 【转载】 Sqlserver查看数据库死锁的SQL语句

    在Sqlsever数据库中,有时候操作数据库过程中会进行锁表操作,在锁表操作的过程中,有时候会出现死锁的情况出现,这时候可以使用SQL语句来查询数据库死锁情况,主要通过系统数据库Master数据库来查 ...

  9. ASP.NET 成功执行Update 的 ExecuteNonQuery() 返回值大于0,但是查看数据库却没有改变

    //真实姓名保存 $("#TrueNameSaveBtn").click(function () { if ($("#TrueNameSaveText").va ...

  10. DEDECMS数据库执行原理、CMS代码层SQL注入防御思路

    我们在上一篇文章中学习了DEDECMS的模板标签.模板解析原理,以及通过对模板核心类的Hook Patch来对模板的解析流量的攻击模式检测,达到修复模板类代码执行漏洞的目的 http://www.cn ...

随机推荐

  1. Oracle ASM磁盘组配置、日常运维、故障处理等操作资料汇总

    ASM(自动存储管理)在数据库中是非常重要的组成部分,它可以为磁盘提供统一的存储管理.提高磁盘访问的性能和可用性.简化管理复杂度,从而为数据库的运行提供更好的支持. 这里就为大家整理了墨天轮数据社区上 ...

  2. 云原生周刊:Meshery v0.70 发布 | 2024.1.22

    开源项目推荐 flux-cluster-template 该项目用于部署由 Flux.SOPS.GitHub Actions.Renovate.Cilium 等支持的 Kubernetes 集群,专注 ...

  3. KubeSphere 社区双周报 | Java functions framework 支持 SkyWalking | 2023.8.4-8.17

    KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...

  4. [NOI Online 2022 入门组] 数学游戏

    P8255 [NOI Online 2022 入门组] 数学游戏 注:妙哉,此题可以理解为数学题. 思路 由题易得: \[\notag z=d_x\times d_y\times \gcd(x,y)^ ...

  5. java中如何将Object类型转换为int类型

    如何将Object类型转换为int类型 Object object = null; try { Integer.parseInt(object.toString()); } catch (Number ...

  6. 多元/多维高斯/正态分布概率密度函数推导 (Derivation of the Multivariate/Multidimensional Normal/Gaussian Density)

    各种维度正态分布公式: 一维正态分布 二维正态分布/多维正态分布 各向同性正态分布 注:即方差都是一样的,均值不一样,方差的值可以单独用标量表示. 多元/多维高斯/正态分布概率密度函数推导 (Deri ...

  7. Selenium操作:测试form表单

    from表单是经常测试的用例,用户登录.注册等都会用到form表单,本文简单设计了一个用户登录的form表单,并对该form表单进行测试 一.自定义form表单 1.用到的组件 如下图,图中定义了一个 ...

  8. python数据结构的性能分析

    2.python数据结构的性能分析 一.引言 - 现在大家对 大O 算法和不同函数之间的差异有了了解.本节的目标是告诉你 Python 列表和字典操作的 大O 性能.然后我们将做一些基于时间的实验来说 ...

  9. Socket Tcp高密集信息广播转发强度测试

    在有些场中存在着大量的消息广播转发,为了了解.net socket tcp在这方面的性能表现,所以做了一个比较极端信息广播转发强度测试.测试场景是以400个连接信息相互广播为测试用例就是当其中一个连接 ...

  10. 使用 LLVM 框架创建有效的编译器,第 2 部分

    使用 clang 预处理 C/C++ 代码 无论您使用哪一种编程语言,LLVM 编译器基础架构都会提供一种强大的方法来优化您的应用程序.在这个两部分系列的第二篇文章中,了解在 LLVM 中测试代码,使 ...