Mariadb JDBC plugin (#4740)

* Add Mariadb JDBC plugin and provide tests

* Refactor component name

* Reformat plugin description and remove healthcheck span from the test

Co-authored-by: Efe Kaptan <Efe.Kaptan@webtrekk.com>
Co-authored-by: zhang-wei <pknfe@outlook.com>
Co-authored-by: 吴晟 Wu Sheng <wu.sheng@foxmail.com>
diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml
index 42069a5..d06107e 100644
--- a/.github/workflows/plugins-test.3.yaml
+++ b/.github/workflows/plugins-test.3.yaml
@@ -43,6 +43,7 @@
           - { name: 'spring-async-scenario', title: 'Spring Async 4.3.x-5.1.x (35)' }
           - { name: 'vertx-eventbus-3.x-scenario', title: 'Vert.x EventBus 3.2.0-3.9.0 (27)' }
           - { name: 'vertx-web-3.x-scenario', title: 'Vert.x Web 3.0.0-3.9.0 (29)' }
+          - { name: 'mariadb-scenario', title: 'Mariadb 2.x (8)' }
     steps:
       - uses: actions/checkout@v2
         with:
diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
index 136ebb6..c608ae3 100755
--- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -156,4 +156,6 @@
     public static final OfficialComponent UNDERTOW = new OfficialComponent(84, "Undertow");
 
     public static final OfficialComponent FINAGLE = new OfficialComponent(85, "Finagle");
+
+    public static final OfficialComponent MARIADB_JDBC = new OfficialComponent(87, "mariadb-jdbc");
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
index 764e514..8a4990d 100755
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
@@ -328,6 +328,22 @@
             public static int SQL_PARAMETERS_MAX_LENGTH = 512;
         }
 
+        public static class MARIADB {
+            /**
+             * If set to true, the parameters of the sql (typically {@link java.sql.PreparedStatement}) would be
+             * collected.
+             */
+            public static boolean TRACE_SQL_PARAMETERS = false;
+
+            /**
+             * For the sake of performance, SkyWalking won't save the entire parameters string into the tag, but only
+             * the first {@code SQL_PARAMETERS_MAX_LENGTH} characters.
+             * <p>
+             * Set a negative number to save the complete parameter string to the tag.
+             */
+            public static int SQL_PARAMETERS_MAX_LENGTH = 512;
+        }
+
         public static class SolrJ {
             /**
              * If true, trace all the query parameters(include deleteByIds and deleteByQuery) in Solr query request,
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/PSSetterDefinitionOfJDBCInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/PSSetterDefinitionOfJDBCInstrumentation.java
index bdb890a..d641ca6 100644
--- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/PSSetterDefinitionOfJDBCInstrumentation.java
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/PSSetterDefinitionOfJDBCInstrumentation.java
@@ -42,7 +42,7 @@
     public ElementMatcher<MethodDescription> getMethodsMatcher() {
         ElementMatcher.Junction<MethodDescription> matcher = none();
 
-        if (Config.Plugin.MySQL.TRACE_SQL_PARAMETERS || Config.Plugin.POSTGRESQL.TRACE_SQL_PARAMETERS) {
+        if (Config.Plugin.MySQL.TRACE_SQL_PARAMETERS || Config.Plugin.POSTGRESQL.TRACE_SQL_PARAMETERS || Config.Plugin.MARIADB.TRACE_SQL_PARAMETERS) {
             final Set<String> setters = ignorable ? PS_IGNORABLE_SETTERS : PS_SETTERS;
             for (String setter : setters) {
                 matcher = matcher.or(named(setter));
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/PreparedStatementParameterBuilder.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/PreparedStatementParameterBuilder.java
new file mode 100644
index 0000000..1209b80
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/PreparedStatementParameterBuilder.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc;
+
+public class PreparedStatementParameterBuilder {
+    private static final String EMPTY_LIST = "[]";
+    private Object[] parameters;
+    private Integer maxIndex;
+    private int maxLength = 0;
+
+    public PreparedStatementParameterBuilder setParameters(Object[] parameters) {
+        this.parameters = parameters;
+        return this;
+    }
+
+    public PreparedStatementParameterBuilder setMaxIndex(int maxIndex) {
+        this.maxIndex = maxIndex;
+        return this;
+    }
+
+    public PreparedStatementParameterBuilder setMaxLength(int maxLength) {
+        this.maxLength = maxLength;
+        return this;
+    }
+
+    public String build() {
+        if (parameters == null) {
+            return EMPTY_LIST;
+        }
+
+        String parameterString = getParameterString();
+        return truncate(parameterString);
+    }
+
+    private String getParameterString() {
+        StringBuilder stringBuilder = new StringBuilder();
+        boolean first = true;
+        for (int i = 0; i < getMaxIndex(); i++) {
+            Object parameter = parameters[i];
+            if (!first) {
+                stringBuilder.append(",");
+            }
+            stringBuilder.append(parameter);
+            first = false;
+        }
+        return String.format("[%s]", stringBuilder.toString());
+    }
+
+    private int getMaxIndex() {
+        int maxIdx = maxIndex != null ? maxIndex : parameters.length;
+        return Math.min(maxIdx, parameters.length);
+    }
+
+    private String truncate(String parameterString) {
+        if (maxLength > 0 && parameterString.length() > maxLength) {
+            parameterString = parameterString.substring(0, maxLength) + "...";
+        }
+
+        return parameterString;
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MariadbURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MariadbURLParser.java
new file mode 100644
index 0000000..65b21e6
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MariadbURLParser.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.connectionurl.parser;
+
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+public class MariadbURLParser extends MysqlURLParser {
+    public MariadbURLParser(String url) {
+        super(url, "Mariadb", ComponentsDefine.MARIADB_JDBC);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java
index 7b86ea7..d4ca1b8 100644
--- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java
@@ -19,6 +19,7 @@
 package org.apache.skywalking.apm.plugin.jdbc.connectionurl.parser;
 
 import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.apache.skywalking.apm.network.trace.component.OfficialComponent;
 import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
 
 /**
@@ -27,12 +28,19 @@
 public class MysqlURLParser extends AbstractURLParser {
 
     private static final int DEFAULT_PORT = 3306;
-    private static final String DB_TYPE = "Mysql";
+    private String dbType = "Mysql";
+    private OfficialComponent component = ComponentsDefine.MYSQL_JDBC_DRIVER;
 
     public MysqlURLParser(String url) {
         super(url);
     }
 
+    public MysqlURLParser(String url, String dbType, OfficialComponent component) {
+        super(url);
+        this.dbType = dbType;
+        this.component = component;
+    }
+
     @Override
     protected URLLocation fetchDatabaseHostsIndexRange() {
         int hostLabelStartIndex = url.indexOf("//");
@@ -87,15 +95,15 @@
                     sb.append(host).append(",");
                 }
             }
-            return new ConnectionInfo(ComponentsDefine.MYSQL_JDBC_DRIVER, DB_TYPE, sb.substring(0, sb.length() - 1), fetchDatabaseNameFromURL());
+            return new ConnectionInfo(component, dbType, sb.substring(0, sb.length() - 1), fetchDatabaseNameFromURL());
         } else {
             String[] hostAndPort = hostSegment[0].split(":");
             if (hostAndPort.length != 1) {
-                return new ConnectionInfo(ComponentsDefine.MYSQL_JDBC_DRIVER, DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL(location
-                    .endIndex()));
+                return new ConnectionInfo(component, dbType, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL(location
+                        .endIndex()));
             } else {
-                return new ConnectionInfo(ComponentsDefine.MYSQL_JDBC_DRIVER, DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL(location
-                    .endIndex()));
+                return new ConnectionInfo(component, dbType, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL(location
+                        .endIndex()));
             }
         }
     }
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java
index 9058065..12c6e04 100644
--- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java
@@ -30,6 +30,7 @@
     private static final String ORACLE_JDBC_URL_PREFIX = "jdbc:oracle";
     private static final String H2_JDBC_URL_PREFIX = "jdbc:h2";
     private static final String POSTGRESQL_JDBC_URL_PREFIX = "jdbc:postgresql";
+    private static final String MARIADB_JDBC_URL_PREFIX = "jdbc:mariadb";
 
     public static ConnectionInfo parser(String url) {
         ConnectionURLParser parser = null;
@@ -42,6 +43,8 @@
             parser = new H2URLParser(url);
         } else if (lowerCaseUrl.startsWith(POSTGRESQL_JDBC_URL_PREFIX)) {
             parser = new PostgreSQLURLParser(url);
+        } else if (lowerCaseUrl.startsWith(MARIADB_JDBC_URL_PREFIX)) {
+            parser = new MariadbURLParser(url);
         }
         return parser.parse();
     }
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/PreparedStatementParameterBuilderTest.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/PreparedStatementParameterBuilderTest.java
new file mode 100644
index 0000000..11d6fa3
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/PreparedStatementParameterBuilderTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class PreparedStatementParameterBuilderTest {
+    private static Object[] PARAMETERS = new Object[]{"test", 1234};
+    private static final String EMPTY_LIST = "[]";
+    private PreparedStatementParameterBuilder builder;
+
+    @Test
+    public void testDefaultBuilder() {
+        builder = new PreparedStatementParameterBuilder();
+        assertThat(builder.build(), is(EMPTY_LIST));
+    }
+
+    @Test
+    public void testNullParameters() {
+        builder = new PreparedStatementParameterBuilder();
+        builder.setParameters(null);
+        assertThat(builder.build(), is(EMPTY_LIST));
+    }
+
+    @Test
+    public void testMaxIndex() {
+        builder = new PreparedStatementParameterBuilder();
+        Object[] parameters = new Object[]{
+                "test",
+                1234,
+                "abcd"
+        };
+        builder.setParameters(parameters).setMaxIndex(2);
+        assertThat(builder.build(), is("[test,1234]"));
+    }
+
+    @Test
+    public void testOutOfRangeOfMaxIndex() {
+        builder = new PreparedStatementParameterBuilder();
+        builder.setParameters(PARAMETERS);
+        builder.setMaxIndex(3);
+        assertThat(builder.build(), is("[test,1234]"));
+
+        builder.setMaxIndex(0);
+        assertThat(builder.build(), is(EMPTY_LIST));
+
+        builder.setMaxIndex(-1);
+        assertThat(builder.build(), is(EMPTY_LIST));
+    }
+
+    @Test
+    public void testParametersString() {
+        builder = new PreparedStatementParameterBuilder();
+        Object[] parameters = new Object[]{
+                "",
+                1234,
+                10.0,
+                null,
+                'c',
+                true,
+                0x100
+        };
+        builder.setParameters(parameters);
+        assertThat(builder.build(), is("[,1234,10.0,null,c,true,256]"));
+    }
+
+    @Test
+    public void testMaxLength() {
+        builder = new PreparedStatementParameterBuilder();
+        builder.setParameters(PARAMETERS);
+        builder.setMaxLength(10);
+        assertThat(builder.build(), is("[test,1234..."));
+    }
+
+    @Test
+    public void testMaxLengthZero() {
+        builder = new PreparedStatementParameterBuilder();
+        builder.setParameters(PARAMETERS);
+        builder.setMaxLength(0);
+        assertThat(builder.build(), is("[test,1234]"));
+    }
+
+    @Test
+    public void testMaxLengthOutOfRange() {
+        builder = new PreparedStatementParameterBuilder();
+        builder.setParameters(PARAMETERS);
+        builder.setMaxLength(20);
+        assertThat(builder.build(), is("[test,1234]"));
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java
index 50b9f50..b832b45 100644
--- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java
@@ -152,4 +152,12 @@
         assertThat(connectionInfo.getDatabaseName(), is("sample"));
         assertThat(connectionInfo.getDatabasePeer(), is("localhost:8084"));
     }
+
+    @Test
+    public void testParseMariadbJDBCURLWithHost() {
+        ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mariadb//primaryhost/test");
+        assertThat(connectionInfo.getDBType(), is("Mariadb"));
+        assertThat(connectionInfo.getDatabaseName(), is("test"));
+        assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3306"));
+    }
 }
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml
new file mode 100644
index 0000000..0288fbe
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml
@@ -0,0 +1,61 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>apm-sdk-plugin</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>8.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>apm-mariadb-2.x-plugin</artifactId>
+    <packaging>jar</packaging>
+
+    <name>mariadb-2.x-plugin</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <mariadb-java-client.version>2.6.0</mariadb-java-client.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.mariadb.jdbc</groupId>
+            <artifactId>mariadb-java-client</artifactId>
+            <version>${mariadb-java-client.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>apm-jdbc-commons</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-deploy-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/Constants.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/Constants.java
new file mode 100644
index 0000000..8e717a6
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/Constants.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
+
+public class Constants {
+    public static final StringTag SQL_PARAMETERS = new StringTag("db.sql.parameters");
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateCallableStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateCallableStatementInterceptor.java
new file mode 100644
index 0000000..212b388
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateCallableStatementInterceptor.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+import java.lang.reflect.Method;
+
+public class CreateCallableStatementInterceptor implements InstanceMethodsAroundInterceptor {
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                             MethodInterceptResult result) {
+
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                              Object ret) {
+        if (ret instanceof EnhancedInstance) {
+            ((EnhancedInstance) ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo) objInst.getSkyWalkingDynamicField(), (String) allArguments[0], "CallableStatement"));
+        }
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                      Class<?>[] argumentsTypes, Throwable t) {
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreatePreparedStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreatePreparedStatementInterceptor.java
new file mode 100644
index 0000000..3b286a6
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreatePreparedStatementInterceptor.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+import java.lang.reflect.Method;
+
+public class CreatePreparedStatementInterceptor implements InstanceMethodsAroundInterceptor {
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                             MethodInterceptResult result) {
+
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                              Object ret) {
+        if (ret instanceof EnhancedInstance) {
+            ((EnhancedInstance) ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo) objInst.getSkyWalkingDynamicField(), (String) allArguments[0], "PreparedStatement"));
+        }
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                      Class<?>[] argumentsTypes, Throwable t) {
+
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateStatementInterceptor.java
new file mode 100644
index 0000000..5113af0
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateStatementInterceptor.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+import java.lang.reflect.Method;
+
+public class CreateStatementInterceptor implements InstanceMethodsAroundInterceptor {
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                             MethodInterceptResult result) {
+
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                              Object ret) {
+        if (ret instanceof EnhancedInstance) {
+            ((EnhancedInstance) ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo) objInst.getSkyWalkingDynamicField(), "", "Statement"));
+        }
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                      Class<?>[] argumentsTypes, Throwable t) {
+
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/PreparedStatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/PreparedStatementExecuteMethodsInterceptor.java
new file mode 100644
index 0000000..c17d94a
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/PreparedStatementExecuteMethodsInterceptor.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.PreparedStatementParameterBuilder;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+import java.lang.reflect.Method;
+
+import static org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.Constants.SQL_PARAMETERS;
+
+public class PreparedStatementExecuteMethodsInterceptor implements InstanceMethodsAroundInterceptor {
+
+    @Override
+    public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                   Class<?>[] argumentsTypes, MethodInterceptResult result) {
+        StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+        ConnectionInfo connectInfo = cacheObject.getConnectionInfo();
+        if (connectInfo == null) {
+            return;
+        }
+        AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject
+                .getStatementName()), connectInfo.getDatabasePeer());
+        Tags.DB_TYPE.set(span, "sql");
+        Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
+        Tags.DB_STATEMENT.set(span, cacheObject.getSql());
+        span.setComponent(connectInfo.getComponent());
+
+        if (Config.Plugin.MARIADB.TRACE_SQL_PARAMETERS) {
+            final Object[] parameters = cacheObject.getParameters();
+            if (parameters != null && parameters.length > 0) {
+                int maxIndex = cacheObject.getMaxIndex();
+                SQL_PARAMETERS.set(span, getParameterString(parameters, maxIndex));
+            }
+        }
+
+        SpanLayer.asDB(span);
+    }
+
+    @Override
+    public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                    Class<?>[] argumentsTypes, Object ret) {
+        StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+        if (cacheObject.getConnectionInfo() != null) {
+            ContextManager.stopSpan();
+        }
+        return ret;
+    }
+
+    @Override
+    public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                            Class<?>[] argumentsTypes, Throwable t) {
+        StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+        if (cacheObject.getConnectionInfo() != null) {
+            ContextManager.activeSpan().errorOccurred().log(t);
+        }
+    }
+
+    private String buildOperationName(ConnectionInfo connectionInfo, String methodName, String statementName) {
+        return connectionInfo.getDBType() + "/JDBI/" + statementName + "/" + methodName;
+    }
+
+    private String getParameterString(Object[] parameters, int maxIndex) {
+        return new PreparedStatementParameterBuilder()
+                .setParameters(parameters)
+                .setMaxIndex(maxIndex)
+                .setMaxLength(Config.Plugin.MARIADB.SQL_PARAMETERS_MAX_LENGTH)
+                .build();
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/SetCatalogInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/SetCatalogInterceptor.java
new file mode 100644
index 0000000..8c25279
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/SetCatalogInterceptor.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+import java.lang.reflect.Method;
+
+public class SetCatalogInterceptor implements InstanceMethodsAroundInterceptor {
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                             MethodInterceptResult result) {
+        Object dynamicField = objInst.getSkyWalkingDynamicField();
+        if (dynamicField instanceof ConnectionInfo) {
+            ((ConnectionInfo) dynamicField).setDatabaseName(String.valueOf(allArguments[0]));
+        }
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                              Object ret) {
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                      Class<?>[] argumentsTypes, Throwable t) {
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/StatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/StatementExecuteMethodsInterceptor.java
new file mode 100644
index 0000000..8f636ce
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/StatementExecuteMethodsInterceptor.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+import java.lang.reflect.Method;
+
+public class StatementExecuteMethodsInterceptor implements InstanceMethodsAroundInterceptor {
+    @Override
+    public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                   Class<?>[] argumentsTypes, MethodInterceptResult result) {
+        StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+        ConnectionInfo connectInfo = cacheObject.getConnectionInfo();
+        if (connectInfo != null) {
+            AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject
+                    .getStatementName()), connectInfo.getDatabasePeer());
+            Tags.DB_TYPE.set(span, "sql");
+            Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
+            String sql = allArguments.length > 0 ? (String) allArguments[0] : "";
+            Tags.DB_STATEMENT.set(span, sql);
+            span.setComponent(connectInfo.getComponent());
+            SpanLayer.asDB(span);
+        }
+    }
+
+    @Override
+    public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                    Class<?>[] argumentsTypes, Object ret) {
+        StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+        if (cacheObject.getConnectionInfo() != null) {
+            ContextManager.stopSpan();
+        }
+        return ret;
+    }
+
+    @Override
+    public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                            Class<?>[] argumentsTypes, Throwable t) {
+        StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+        if (cacheObject.getConnectionInfo() != null) {
+            ContextManager.activeSpan().errorOccurred().log(t);
+        }
+    }
+
+    private String buildOperationName(ConnectionInfo connectionInfo, String methodName, String statementName) {
+        return connectionInfo.getDBType() + "/JDBI/" + statementName + "/" + methodName;
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/ConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/ConnectionInstrumentation.java
new file mode 100644
index 0000000..45ddf69
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/ConnectionInstrumentation.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.plugin.jdbc.define.Constants;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+public class ConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = "org.mariadb.jdbc.MariaDbConnection";
+    private static final String CREATE_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.CreateStatementInterceptor";
+    private static final String CREATE_PREPARED_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.CreatePreparedStatementInterceptor";
+    private static final String CREATE_CALLABLE_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.CreateCallableStatementInterceptor";
+    private static final String SET_CATALOG_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.SetCatalogInterceptor";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[0];
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named(Constants.CREATE_STATEMENT_METHOD_NAME);
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return CREATE_STATEMENT_INTERCEPTOR_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                },
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named(Constants.PREPARE_STATEMENT_METHOD_NAME);
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return CREATE_PREPARED_STATEMENT_INTERCEPTOR_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                },
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named(Constants.PREPARE_CALL_METHOD_NAME);
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return CREATE_CALLABLE_STATEMENT_INTERCEPTOR_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                },
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named(Constants.COMMIT_METHOD_NAME)
+                                .or(named(Constants.ROLLBACK_METHOD_NAME))
+                                .or(named(Constants.CLOSE_METHOD_NAME))
+                                .or(named(Constants.RELEASE_SAVE_POINT_METHOD_NAME));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return Constants.SERVICE_METHOD_INTERCEPT_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                },
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named("setCatalog");
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return SET_CATALOG_INTERCEPTOR_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/DriverInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/DriverInstrumentation.java
new file mode 100644
index 0000000..f59ef43
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/DriverInstrumentation.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define;
+
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.plugin.jdbc.define.AbstractDriverInstrumentation;
+
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * {@link DriverInstrumentation} presents that skywalking intercepts {@link org.mariadb.jdbc.Driver}.
+ */
+public class DriverInstrumentation extends AbstractDriverInstrumentation {
+    private static final String ENHANCE_CLASS = "org.mariadb.jdbc.Driver";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementIgnoredSetterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementIgnoredSetterInstrumentation.java
new file mode 100644
index 0000000..17f528e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementIgnoredSetterInstrumentation.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.plugin.jdbc.PSSetterDefinitionOfJDBCInstrumentation;
+
+public class PreparedStatementIgnoredSetterInstrumentation extends PreparedStatementInstrumentation {
+
+    @Override
+    public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+                new PSSetterDefinitionOfJDBCInstrumentation(true)
+        };
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementInstrumentation.java
new file mode 100644
index 0000000..c1b1afe
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementInstrumentation.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch.byMultiClassMatch;
+
+public class PreparedStatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String CLIENT_SIDE_PREPARED_STATEMENT_CLASS_2_0_X = "org.mariadb.jdbc.MariaDbPreparedStatementClient";
+    private static final String CLIENT_SIDE_PREPARED_STATEMENT_CLASS_2_4_X = "org.mariadb.jdbc.ClientSidePreparedStatement";
+    private static final String SERVER_SIDE_PREPARED_STATEMENT_CLASS_2_0_X = "org.mariadb.jdbc.MariaDbPreparedStatementServer";
+    private static final String SERVER_SIDE_PREPARED_STATEMENT_CLASS_2_4_X = "org.mariadb.jdbc.ServerSidePreparedStatement";
+    private static final String PREPARED_STATEMENT_EXECUTE_METHODS_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.PreparedStatementExecuteMethodsInterceptor";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byMultiClassMatch(
+                CLIENT_SIDE_PREPARED_STATEMENT_CLASS_2_0_X,
+                CLIENT_SIDE_PREPARED_STATEMENT_CLASS_2_4_X,
+                SERVER_SIDE_PREPARED_STATEMENT_CLASS_2_0_X,
+                SERVER_SIDE_PREPARED_STATEMENT_CLASS_2_4_X
+        );
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[0];
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named("execute")
+                                .or(named("executeQuery"))
+                                .or(named("executeUpdate"));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return PREPARED_STATEMENT_EXECUTE_METHODS_INTERCEPTOR_CLASS;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementNullSetterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementNullSetterInstrumentation.java
new file mode 100644
index 0000000..e4cb3ec
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementNullSetterInstrumentation.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.plugin.jdbc.JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint;
+
+public class PreparedStatementNullSetterInstrumentation extends PreparedStatementInstrumentation {
+
+    @Override
+    public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+                new JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint()
+        };
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementSetterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementSetterInstrumentation.java
new file mode 100644
index 0000000..7f58dfd
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/PreparedStatementSetterInstrumentation.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.plugin.jdbc.PSSetterDefinitionOfJDBCInstrumentation;
+
+public class PreparedStatementSetterInstrumentation extends PreparedStatementInstrumentation {
+
+    @Override
+    public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+                new PSSetterDefinitionOfJDBCInstrumentation(false)
+        };
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/StatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/StatementInstrumentation.java
new file mode 100644
index 0000000..8d7bfbd
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/define/StatementInstrumentation.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+public class StatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+    private static final String MARIADB_STATEMENT_CLASS_NAME = "org.mariadb.jdbc.MariaDbStatement";
+    private static final String STATEMENT_EXECUTE_METHODS_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.StatementExecuteMethodsInterceptor";
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[0];
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                        return named("execute")
+                                .or(named("executeQuery"))
+                                .or(named("executeUpdate"))
+                                .or(named("executeLargeUpdate"))
+                                .or(named("executeBatch"))
+                                .or(named("executeLargeBatch"));
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return STATEMENT_EXECUTE_METHODS_INTERCEPTOR;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return false;
+                    }
+                }
+        };
+    }
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byName(MARIADB_STATEMENT_CLASS_NAME);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000..65c37bf
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+mariadb-2.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define.DriverInstrumentation
+mariadb-2.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define.ConnectionInstrumentation
+mariadb-2.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define.StatementInstrumentation
+mariadb-2.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define.PreparedStatementInstrumentation
+mariadb-2.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define.PreparedStatementSetterInstrumentation
+mariadb-2.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define.PreparedStatementNullSetterInstrumentation
+mariadb-2.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v2.define.PreparedStatementIgnoredSetterInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateCallableStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateCallableStatementInterceptorTest.java
new file mode 100644
index 0000000..5979c2c
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateCallableStatementInterceptorTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CreateCallableStatementInterceptorTest {
+
+    private static final String SQL = "Select * from test";
+
+    private CreateCallableStatementInterceptor interceptor;
+
+    @Mock
+    private EnhancedInstance ret;
+
+    @Mock
+    private EnhancedInstance objectInstance;
+
+    @Mock
+    private ConnectionInfo connectionInfo;
+
+    @Before
+    public void setUp() {
+        interceptor = new CreateCallableStatementInterceptor();
+
+        when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo);
+    }
+
+    @Test
+    public void testResultIsEnhanceInstance() {
+        interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, ret);
+        verify(ret).setSkyWalkingDynamicField(Matchers.any());
+    }
+
+    @Test
+    public void testResultIsNotEnhanceInstance() {
+        interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, new Object());
+        verify(ret, times(0)).setSkyWalkingDynamicField(Matchers.any());
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreatePreparedStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreatePreparedStatementInterceptorTest.java
new file mode 100644
index 0000000..4141c04
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreatePreparedStatementInterceptorTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CreatePreparedStatementInterceptorTest {
+
+    private static final String SQL = "Select * from test";
+
+    private CreatePreparedStatementInterceptor interceptor;
+
+    @Mock
+    private EnhancedInstance ret;
+
+    @Mock
+    private EnhancedInstance objectInstance;
+
+    @Mock
+    private ConnectionInfo connectionInfo;
+
+    @Before
+    public void setUp() {
+        interceptor = new CreatePreparedStatementInterceptor();
+
+        when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo);
+    }
+
+    @Test
+    public void testResultIsEnhanceInstance() {
+        interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, ret);
+        verify(ret).setSkyWalkingDynamicField(Matchers.any());
+    }
+
+    @Test
+    public void testResultIsNotEnhanceInstance() {
+        interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, new Object());
+        verify(ret, times(0)).setSkyWalkingDynamicField(Matchers.any());
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateStatementInterceptorTest.java
new file mode 100644
index 0000000..6292a4b
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/CreateStatementInterceptorTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CreateStatementInterceptorTest {
+
+    private static final String SQL = "Select * from test";
+
+    private CreateStatementInterceptor interceptor;
+
+    @Mock
+    private EnhancedInstance ret;
+
+    @Mock
+    private EnhancedInstance objectInstance;
+
+    @Mock
+    private ConnectionInfo connectionInfo;
+
+    @Before
+    public void setUp() {
+        interceptor = new CreateStatementInterceptor();
+
+        when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo);
+    }
+
+    @Test
+    public void testResultIsEnhanceInstance() {
+        interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, ret);
+        verify(ret).setSkyWalkingDynamicField(Matchers.any());
+    }
+
+    @Test
+    public void testResultIsNotEnhanceInstance() {
+        interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, new Object());
+        verify(ret, times(0)).setSkyWalkingDynamicField(Matchers.any());
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/PreparedStatementExecuteMethodsInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/PreparedStatementExecuteMethodsInterceptorTest.java
new file mode 100644
index 0000000..8742842
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/PreparedStatementExecuteMethodsInterceptorTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.apache.skywalking.apm.agent.test.tools.SpanAssert;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.apache.skywalking.apm.plugin.jdbc.JDBCPreparedStatementSetterInterceptor;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+import java.lang.reflect.Method;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class PreparedStatementExecuteMethodsInterceptorTest {
+
+    private static final String SQL = "Select * from test where id = ?";
+
+    @SegmentStoragePoint
+    private SegmentStorage segmentStorage;
+
+    @Rule
+    public AgentServiceRule serviceRule = new AgentServiceRule();
+
+    private PreparedStatementExecuteMethodsInterceptor serviceMethodInterceptor;
+
+    private JDBCPreparedStatementSetterInterceptor preparedStatementSetterInterceptor;
+
+    @Mock
+    private ConnectionInfo connectionInfo;
+    @Mock
+    private EnhancedInstance objectInstance;
+    @Mock
+    private Method method;
+    private StatementEnhanceInfos enhanceRequireCacheObject;
+
+    @Before
+    public void setUp() {
+        Config.Plugin.MARIADB.TRACE_SQL_PARAMETERS = true;
+        preparedStatementSetterInterceptor = new JDBCPreparedStatementSetterInterceptor();
+        serviceMethodInterceptor = new PreparedStatementExecuteMethodsInterceptor();
+
+        enhanceRequireCacheObject = new StatementEnhanceInfos(connectionInfo, SQL, "PreparedStatement");
+        when(objectInstance.getSkyWalkingDynamicField()).thenReturn(enhanceRequireCacheObject);
+        when(method.getName()).thenReturn("executeQuery");
+        when(connectionInfo.getComponent()).thenReturn(ComponentsDefine.MARIADB_JDBC);
+        when(connectionInfo.getDBType()).thenReturn("Mariadb");
+        when(connectionInfo.getDatabaseName()).thenReturn("test");
+        when(connectionInfo.getDatabasePeer()).thenReturn("localhost:3306");
+    }
+
+    @Test
+    public void testExecutePreparedStatement() throws Throwable {
+        preparedStatementSetterInterceptor.beforeMethod(objectInstance, method, new Object[]{1, "abcd"}, null, null);
+        preparedStatementSetterInterceptor.beforeMethod(objectInstance, method, new Object[]{2, "efgh"}, null, null);
+
+        serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[]{SQL}, null, null);
+        serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[]{SQL}, null, null);
+
+        assertThat(segmentStorage.getTraceSegments().size(), is(1));
+        TraceSegment segment = segmentStorage.getTraceSegments().get(0);
+        assertThat(SegmentHelper.getSpans(segment).size(), is(1));
+        AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0);
+        SpanAssert.assertLayer(span, SpanLayer.DB);
+        assertThat(span.getOperationName(), is("Mariadb/JDBI/PreparedStatement/"));
+        SpanAssert.assertTag(span, 0, "sql");
+        SpanAssert.assertTag(span, 1, "test");
+        SpanAssert.assertTag(span, 2, SQL);
+        SpanAssert.assertTag(span, 3, "[abcd,efgh]");
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/StatementExecuteMethodsInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/StatementExecuteMethodsInterceptorTest.java
new file mode 100644
index 0000000..9b877bb
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v2/StatementExecuteMethodsInterceptorTest.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.jdbc.mariadb.v2;
+
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.apache.skywalking.apm.agent.test.tools.SpanAssert;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+import java.lang.reflect.Method;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class StatementExecuteMethodsInterceptorTest {
+
+    private static final String SQL = "Select * from test";
+
+    @SegmentStoragePoint
+    private SegmentStorage segmentStorage;
+
+    @Rule
+    public AgentServiceRule serviceRule = new AgentServiceRule();
+
+    private StatementExecuteMethodsInterceptor serviceMethodInterceptor;
+
+    @Mock
+    private ConnectionInfo connectionInfo;
+    @Mock
+    private EnhancedInstance objectInstance;
+    @Mock
+    private Method method;
+    private StatementEnhanceInfos enhanceRequireCacheObject;
+
+    @Before
+    public void setUp() {
+        serviceMethodInterceptor = new StatementExecuteMethodsInterceptor();
+
+        enhanceRequireCacheObject = new StatementEnhanceInfos(connectionInfo, SQL, "CallableStatement");
+        when(objectInstance.getSkyWalkingDynamicField()).thenReturn(enhanceRequireCacheObject);
+        when(method.getName()).thenReturn("executeQuery");
+        when(connectionInfo.getComponent()).thenReturn(ComponentsDefine.MARIADB_JDBC);
+        when(connectionInfo.getDBType()).thenReturn("Mariadb");
+        when(connectionInfo.getDatabaseName()).thenReturn("test");
+        when(connectionInfo.getDatabasePeer()).thenReturn("localhost:3306");
+    }
+
+    @Test
+    public void testExecuteStatement() {
+        serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[]{SQL}, null, null);
+        serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[]{SQL}, null, null);
+
+        assertThat(segmentStorage.getTraceSegments().size(), is(1));
+        TraceSegment segment = segmentStorage.getTraceSegments().get(0);
+        assertThat(SegmentHelper.getSpans(segment).size(), is(1));
+        AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0);
+        SpanAssert.assertLayer(span, SpanLayer.DB);
+        assertThat(span.getOperationName(), is("Mariadb/JDBI/CallableStatement/"));
+        SpanAssert.assertTag(span, 0, "sql");
+        SpanAssert.assertTag(span, 1, "test");
+        SpanAssert.assertTag(span, 2, SQL);
+    }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/PreparedStatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/PreparedStatementExecuteMethodsInterceptor.java
index 91b0186..fa0613a 100644
--- a/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/PreparedStatementExecuteMethodsInterceptor.java
+++ b/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/PreparedStatementExecuteMethodsInterceptor.java
@@ -26,6 +26,7 @@
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.PreparedStatementParameterBuilder;
 import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
 import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
 
@@ -37,7 +38,7 @@
 
     @Override
     public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
-        Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+                                   Class<?>[] argumentsTypes, MethodInterceptResult result) {
         StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
         ConnectionInfo connectInfo = cacheObject.getConnectionInfo();
         /**
@@ -49,7 +50,7 @@
         if (connectInfo != null) {
 
             AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject
-                .getStatementName()), connectInfo.getDatabasePeer());
+                    .getStatementName()), connectInfo.getDatabasePeer());
             Tags.DB_TYPE.set(span, "sql");
             Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
             Tags.DB_STATEMENT.set(span, cacheObject.getSql());
@@ -59,11 +60,7 @@
                 final Object[] parameters = cacheObject.getParameters();
                 if (parameters != null && parameters.length > 0) {
                     int maxIndex = cacheObject.getMaxIndex();
-                    String parameterString = buildParameterString(parameters, maxIndex);
-                    int sqlParametersMaxLength = Config.Plugin.MySQL.SQL_PARAMETERS_MAX_LENGTH;
-                    if (sqlParametersMaxLength > 0 && parameterString.length() > sqlParametersMaxLength) {
-                        parameterString = parameterString.substring(0, sqlParametersMaxLength) + "...";
-                    }
+                    String parameterString = getParameterString(parameters, maxIndex);
                     SQL_PARAMETERS.set(span, parameterString);
                 }
             }
@@ -74,7 +71,7 @@
 
     @Override
     public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
-        Class<?>[] argumentsTypes, Object ret) throws Throwable {
+                                    Class<?>[] argumentsTypes, Object ret) {
         StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
         if (cacheObject.getConnectionInfo() != null) {
             ContextManager.stopSpan();
@@ -84,7 +81,7 @@
 
     @Override
     public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
-        Class<?>[] argumentsTypes, Throwable t) {
+                                            Class<?>[] argumentsTypes, Throwable t) {
         StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
         if (cacheObject.getConnectionInfo() != null) {
             ContextManager.activeSpan().errorOccurred().log(t);
@@ -95,18 +92,11 @@
         return connectionInfo.getDBType() + "/JDBI/" + statementName + "/" + methodName;
     }
 
-    private String buildParameterString(Object[] parameters, int maxIndex) {
-        String parameterString = "[";
-        boolean first = true;
-        for (int i = 0; i < maxIndex; i++) {
-            Object parameter = parameters[i];
-            if (!first) {
-                parameterString += ",";
-            }
-            parameterString += parameter;
-            first = false;
-        }
-        parameterString += "]";
-        return parameterString;
+    private String getParameterString(Object[] parameters, int maxIndex) {
+        return new PreparedStatementParameterBuilder()
+                .setParameters(parameters)
+                .setMaxIndex(maxIndex)
+                .setMaxLength(Config.Plugin.MySQL.SQL_PARAMETERS_MAX_LENGTH)
+                .build();
     }
 }
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml
index 2db840d..1c9d9d2 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -88,6 +88,7 @@
         <module>lettuce-5.x-plugin</module>
         <module>avro-plugin</module>
         <module>finagle-6.25.x-plugin</module>
+        <module>mariadb-2.x-plugin</module>
     </modules>
     <packaging>pom</packaging>
 
diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/PreparedStatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/PreparedStatementExecuteMethodsInterceptor.java
index 5a76cf3..151c37e 100755
--- a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/PreparedStatementExecuteMethodsInterceptor.java
+++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/postgresql/PreparedStatementExecuteMethodsInterceptor.java
@@ -18,7 +18,6 @@
 
 package org.apache.skywalking.apm.plugin.jdbc.postgresql;
 
-import java.lang.reflect.Method;
 import org.apache.skywalking.apm.agent.core.conf.Config;
 import org.apache.skywalking.apm.agent.core.context.ContextManager;
 import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
@@ -28,9 +27,12 @@
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.PreparedStatementParameterBuilder;
 import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
 import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
 
+import java.lang.reflect.Method;
+
 /**
  * {@link PreparedStatementExecuteMethodsInterceptor} create the exit span when the client call the interceptor
  * methods.
@@ -41,11 +43,11 @@
 
     @Override
     public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
-        Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+                                   Class<?>[] argumentsTypes, MethodInterceptResult result) {
         StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
         ConnectionInfo connectInfo = cacheObject.getConnectionInfo();
         AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject.getStatementName()), connectInfo
-            .getDatabasePeer());
+                .getDatabasePeer());
         Tags.DB_TYPE.set(span, "sql");
         Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
         Tags.DB_STATEMENT.set(span, cacheObject.getSql());
@@ -55,11 +57,7 @@
             final Object[] parameters = cacheObject.getParameters();
             if (parameters != null && parameters.length > 0) {
                 int maxIndex = cacheObject.getMaxIndex();
-                String parameterString = buildParameterString(parameters, maxIndex);
-                int sqlParametersMaxLength = Config.Plugin.POSTGRESQL.SQL_PARAMETERS_MAX_LENGTH;
-                if (sqlParametersMaxLength > 0 && parameterString.length() > sqlParametersMaxLength) {
-                    parameterString = parameterString.substring(0, sqlParametersMaxLength) + "..." + "]";
-                }
+                String parameterString = getParameterString(parameters, maxIndex);
                 SQL_PARAMETERS.set(span, parameterString);
             }
         }
@@ -69,7 +67,7 @@
 
     @Override
     public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
-        Class<?>[] argumentsTypes, Object ret) throws Throwable {
+                                    Class<?>[] argumentsTypes, Object ret) {
         StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
         if (cacheObject.getConnectionInfo() != null) {
             ContextManager.stopSpan();
@@ -79,7 +77,7 @@
 
     @Override
     public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
-        Class<?>[] argumentsTypes, Throwable t) {
+                                            Class<?>[] argumentsTypes, Throwable t) {
         StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
         if (cacheObject.getConnectionInfo() != null) {
             ContextManager.activeSpan().errorOccurred().log(t);
@@ -90,18 +88,11 @@
         return connectionInfo.getDBType() + "/JDBI/" + statementName + "/" + methodName;
     }
 
-    private String buildParameterString(Object[] parameters, int maxIndex) {
-        String parameterString = "[";
-        boolean first = true;
-        for (int i = 0; i < maxIndex; i++) {
-            Object parameter = parameters[i];
-            if (!first) {
-                parameterString += ",";
-            }
-            parameterString += parameter;
-            first = false;
-        }
-        parameterString += "]";
-        return parameterString;
+    private String getParameterString(Object[] parameters, int maxIndex) {
+        return new PreparedStatementParameterBuilder()
+                .setParameters(parameters)
+                .setMaxIndex(maxIndex)
+                .setMaxLength(Config.Plugin.POSTGRESQL.SQL_PARAMETERS_MAX_LENGTH)
+                .build();
     }
 }
diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md
index acd80bf..a1b4f60 100755
--- a/docs/en/setup/service-agent/java-agent/README.md
+++ b/docs/en/setup/service-agent/java-agent/README.md
@@ -114,6 +114,8 @@
 `plugin.mysql.sql_parameters_max_length`|If set to positive number, the `db.sql.parameters` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.|`512`|
 `plugin.postgresql.trace_sql_parameters`|If set to true, the parameters of the sql (typically `java.sql.PreparedStatement`) would be collected.|`false`|
 `plugin.postgresql.sql_parameters_max_length`|If set to positive number, the `db.sql.parameters` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.|`512`|
+`plugin.mariadb.trace_sql_parameters`|If set to true, the parameters of the sql (typically `java.sql.PreparedStatement`) would be collected.|`false`|
+`plugin.mariadb.sql_parameters_max_length`|If set to positive number, the `db.sql.parameters` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.|`512`|
 `plugin.solrj.trace_statement`|If true, trace all the query parameters(include deleteByIds and deleteByQuery) in Solr query request, default is false.|`false`|
 `plugin.solrj.trace_ops_params`|If true, trace all the operation parameters in Solr request, default is false.|`false`|
 `plugin.light4j.trace_handler_chain`|If true, trace all middleware/business handlers that are part of the Light4J handler chain for a request.|false|
diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md
index 735f185..abb8533 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -32,6 +32,7 @@
   * [Sharding-JDBC](https://github.com/shardingjdbc/sharding-jdbc) 1.5.x
   * [ShardingSphere](https://github.com/apache/incubator-shardingsphere) 3.0.0, 4.0.0-RC1
   * PostgreSQL Driver 8.x, 9.x, 42.x
+  * Mariadb Driver 2.x, 1.8
 * RPC Frameworks
   * [Dubbo](https://github.com/alibaba/dubbo) 2.5.4 -> 2.6.0
   * [Dubbox](https://github.com/dangdangdotcom/dubbox) 2.8.4
diff --git a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml
index 04d8298..9de8925 100755
--- a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml
+++ b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml
@@ -287,6 +287,12 @@
 Finagle:
   id: 85
   languages: Java,Scala
+Mariadb:
+  id: 86
+  languages: Java
+mariadb-jdbc:
+  id: 87
+  languages: Java
 
 # .NET/.NET Core components
 # [3000, 4000) for C#/.NET only
@@ -414,3 +420,4 @@
   pulsar-producer: Pulsar
   pulsar-consumer: Pulsar
   rest-high-level-client: Elasticsearch
+  mariadb-jdbc: Mariadb
diff --git a/oap-server/server-core/src/test/resources/component-libraries.yml b/oap-server/server-core/src/test/resources/component-libraries.yml
index 643b0b2..44a9d12 100755
--- a/oap-server/server-core/src/test/resources/component-libraries.yml
+++ b/oap-server/server-core/src/test/resources/component-libraries.yml
@@ -251,6 +251,12 @@
 Finagle:
   id: 85
   languages: Java,Scala
+Mariadb:
+  id: 86
+  languages: Java
+mariadb-jdbc:
+  id: 87
+  languages: Java
 
 
 # .NET/.NET Core components
@@ -352,3 +358,4 @@
   rest-high-level-client: Elasticsearch
   SolrJ: Solr
   cassandra-java-driver: Cassandra
+  mariadb-jdbc: Mariadb
diff --git a/test/plugin/scenarios/mariadb-scenario/bin/startup.sh b/test/plugin/scenarios/mariadb-scenario/bin/startup.sh
new file mode 100644
index 0000000..5885885
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/bin/startup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+home="$(cd "$(dirname $0)"; pwd)"
+
+java -jar ${agent_opts} ${home}/../libs/mariadb-scenario.jar &
\ No newline at end of file
diff --git a/test/plugin/scenarios/mariadb-scenario/config/expectedData.yaml b/test/plugin/scenarios/mariadb-scenario/config/expectedData.yaml
new file mode 100644
index 0000000..37e1b34
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/config/expectedData.yaml
@@ -0,0 +1,119 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+segmentItems:
+- serviceName: mariadb-scenario
+  segmentSize: ge 1
+  segments:
+  - segmentId: not null
+    spans:
+    - operationName: Mariadb/JDBI/Statement/execute
+      operationId: eq 0
+      parentSpanId: 0
+      spanId: 1
+      spanLayer: Database
+      startTime: nq 0
+      endTime: nq 0
+      componentId: 87
+      isError: false
+      spanType: Exit
+      peer: mariadb-server:3306
+      skipAnalysis: 'false'
+      tags:
+      - {key: db.type, value: sql}
+      - {key: db.instance, value: test}
+      - key: db.statement
+        value: "CREATE TABLE test_table(\nid VARCHAR(1) PRIMARY KEY, \nvalue VARCHAR(10)\
+          \ NOT NULL)"
+    - operationName: Mariadb/JDBI/PreparedStatement/execute
+      operationId: eq 0
+      parentSpanId: 0
+      spanId: 2
+      spanLayer: Database
+      startTime: nq 0
+      endTime: nq 0
+      componentId: 87
+      isError: false
+      spanType: Exit
+      peer: mariadb-server:3306
+      skipAnalysis: 'false'
+      tags:
+      - {key: db.type, value: sql}
+      - {key: db.instance, value: test}
+      - {key: db.statement, value: "INSERT INTO test_table(id, value) VALUES(?,?)"}
+    - operationName: Mariadb/JDBI/PreparedStatement/execute
+      operationId: eq 0
+      parentSpanId: 0
+      spanId: 3
+      spanLayer: Database
+      startTime: nq 0
+      endTime: nq 0
+      componentId: 87
+      isError: false
+      spanType: Exit
+      peer: mariadb-server:3306
+      skipAnalysis: 'false'
+      tags:
+      - {key: db.type, value: sql}
+      - {key: db.instance, value: test}
+      - {key: db.statement, value: "SELECT id, value FROM test_table WHERE id = ?"}
+    - operationName: Mariadb/JDBI/Statement/execute
+      operationId: eq 0
+      parentSpanId: 0
+      spanId: 4
+      spanLayer: Database
+      startTime: nq 0
+      endTime: nq 0
+      componentId: 87
+      isError: false
+      spanType: Exit
+      peer: mariadb-server:3306
+      skipAnalysis: 'false'
+      tags:
+      - {key: db.type, value: sql}
+      - {key: db.instance, value: test}
+      - {key: db.statement, value: "DROP table test_table"}
+    - operationName: Mariadb/JDBI/Connection/close
+      operationId: eq 0
+      parentSpanId: 0
+      spanId: 5
+      spanLayer: Database
+      startTime: nq 0
+      endTime: nq 0
+      componentId: 87
+      isError: false
+      spanType: Exit
+      peer: mariadb-server:3306
+      skipAnalysis: 'false'
+      tags:
+      - {key: db.type, value: sql}
+      - {key: db.instance, value: test}
+      - {key: db.statement, value: ''}
+    - operationName: /mariadb-scenario/case/mariadb-scenario
+      operationId: eq 0
+      parentSpanId: -1
+      spanId: 0
+      startTime: nq 0
+      endTime: nq 0
+      spanLayer: Http
+      isError: false
+      spanType: Entry
+      peer: ''
+      componentId: 1
+      tags:
+      - {key: url, value: 'http://localhost:8080/mariadb-scenario/case/mariadb-scenario'}
+      - {key: http.method, value: GET}
+      logs: []
+      skipAnalysis: 'false'
diff --git a/test/plugin/scenarios/mariadb-scenario/configuration.yml b/test/plugin/scenarios/mariadb-scenario/configuration.yml
new file mode 100644
index 0000000..73e4c48
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/configuration.yml
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+type: jvm
+entryService: http://localhost:8080/mariadb-scenario/case/mariadb-scenario
+healthCheck: http://localhost:8080/mariadb-scenario/case/healthCheck
+startScript: ./bin/startup.sh
+environment:
+depends_on:
+  - mariadb-server
+dependencies:
+  mariadb-server:
+    image: mariadb:10.5.2
+    hostname: mariadb-server
+    expose:
+      - "3306"
+    environment:
+      - MYSQL_ROOT_PASSWORD=root
+      - MYSQL_DATABASE=test
diff --git a/test/plugin/scenarios/mariadb-scenario/pom.xml b/test/plugin/scenarios/mariadb-scenario/pom.xml
new file mode 100644
index 0000000..6e155ba
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/pom.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <groupId>org.apache.skywalking.apm.testcase</groupId>
+    <artifactId>mariadb-scenario</artifactId>
+    <version>1.0.0</version>
+    <packaging>jar</packaging>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <compiler.version>1.8</compiler.version>
+
+        <test.framework.version>2.6.0</test.framework.version>
+        <docker.image.version>${test.framework.version}</docker.image.version>
+
+        <spring-boot-version>2.1.6.RELEASE</spring-boot-version>
+    </properties>
+
+    <name>skywalking-mariadb-scenario</name>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot-version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-log4j2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mariadb.jdbc</groupId>
+            <artifactId>mariadb-java-client</artifactId>
+            <version>${test.framework.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>mariadb-scenario</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${compiler.version}</source>
+                    <target>${compiler.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>src/main/assembly/assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>./target/</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/test/plugin/scenarios/mariadb-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/mariadb-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..54b00bc
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<assembly
+    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <fileSets>
+        <fileSet>
+            <directory>./bin</directory>
+            <fileMode>0775</fileMode>
+        </fileSet>
+    </fileSets>
+
+    <files>
+        <file>
+            <source>${project.build.directory}/mariadb-scenario.jar</source>
+            <outputDirectory>./libs</outputDirectory>
+            <fileMode>0775</fileMode>
+        </file>
+    </files>
+</assembly>
diff --git a/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/Application.java b/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/Application.java
new file mode 100644
index 0000000..2c71b3b
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/Application.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.mariadb;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+    private static final Logger logger = LogManager.getLogger(Application.class);
+
+    public static void main(String[] args) {
+        try {
+            SpringApplication.run(Application.class, args);
+        } catch (Exception ex) {
+            logger.error("Application start error", ex);
+            throw ex;
+        }
+    }
+}
diff --git a/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/MariadbConfig.java b/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/MariadbConfig.java
new file mode 100644
index 0000000..d4e873b
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/MariadbConfig.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.mariadb;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class MariadbConfig {
+    private static Logger logger = LogManager.getLogger(MariadbConfig.class);
+    private static String url;
+    private static String userName;
+    private static String password;
+
+    static {
+        InputStream inputStream = MariadbConfig.class.getClassLoader().getResourceAsStream("/jdbc.properties");
+        Properties properties = new Properties();
+        try {
+            properties.load(inputStream);
+        } catch (IOException e) {
+            logger.error("Failed to load config", e);
+        }
+
+        url = properties.getProperty("mariadb.url");
+        userName = properties.getProperty("mariadb.username");
+        password = properties.getProperty("mariadb.password");
+    }
+
+    public static String getUrl() {
+        return url;
+    }
+
+    public static String getUserName() {
+        return userName;
+    }
+
+    public static String getPassword() {
+        return password;
+    }
+}
diff --git a/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/SQLExecutor.java b/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/SQLExecutor.java
new file mode 100644
index 0000000..e56b33f
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/SQLExecutor.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.mariadb;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class SQLExecutor implements AutoCloseable {
+    private static Logger logger = LogManager.getLogger(SQLExecutor.class);
+    private Connection connection;
+
+    public SQLExecutor() throws SQLException {
+        try {
+            Class.forName("org.mariadb.jdbc.Driver");
+        } catch (ClassNotFoundException ex) {
+            logger.error(ex);
+        }
+        connection = DriverManager.getConnection(MariadbConfig.getUrl(), MariadbConfig.getUserName(), MariadbConfig.getPassword());
+    }
+
+    public void execute(String sql) throws SQLException {
+        Statement statement = connection.createStatement();
+        statement.execute(sql);
+    }
+
+    public void insertData(String sql, String id, String value) throws SQLException {
+        PreparedStatement preparedStatement = connection.prepareStatement(sql);
+        preparedStatement.setString(1, id);
+        preparedStatement.setString(2, value);
+        preparedStatement.execute();
+    }
+
+    public void queryData(String sql, String id) throws SQLException {
+        PreparedStatement preparedStatement = connection.prepareStatement(sql);
+        preparedStatement.setString(1, id);
+        preparedStatement.execute();
+    }
+
+    public void closeConnection() throws SQLException {
+        if (this.connection != null) {
+            this.connection.close();
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        closeConnection();
+    }
+}
diff --git a/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/controller/CaseController.java b/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/controller/CaseController.java
new file mode 100644
index 0000000..72136c5
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/controller/CaseController.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.mariadb.controller;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.skywalking.apm.testcase.mariadb.SQLExecutor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.sql.SQLException;
+
+@RestController
+@RequestMapping("/case")
+public class CaseController {
+
+    private static final Logger logger = LogManager.getLogger(CaseController.class);
+
+    private static final String SUCCESS = "Success";
+
+    private static final String CREATE_TABLE_SQL = "CREATE TABLE test_table(\n" + "id VARCHAR(1) PRIMARY KEY, \n" + "value VARCHAR(10) NOT NULL)";
+    private static final String INSERT_DATA_SQL = "INSERT INTO test_table(id, value) VALUES(?,?)";
+    private static final String QUERY_DATA_SQL = "SELECT id, value FROM test_table WHERE id = ?";
+    private static final String DELETE_DATA_SQL = "DELETE FROM test_table WHERE id=?";
+    private static final String DROP_TABLE_SQL = "DROP table test_table";
+
+    @RequestMapping("/mariadb-scenario")
+    @ResponseBody
+    public String testcase() throws Exception {
+        try (SQLExecutor sqlExecute = new SQLExecutor()) {
+            sqlExecute.execute(CREATE_TABLE_SQL);
+            sqlExecute.insertData(INSERT_DATA_SQL, "1", "value");
+            sqlExecute.queryData(QUERY_DATA_SQL, "1");
+            sqlExecute.execute(DROP_TABLE_SQL);
+        } catch (Exception ex) {
+            logger.error("Failed to execute sql.", ex);
+            throw ex;
+        }
+        return SUCCESS;
+    }
+
+    @RequestMapping("/healthCheck")
+    @ResponseBody
+    public String healthCheck() throws Exception {
+        return SUCCESS;
+    }
+
+}
diff --git a/test/plugin/scenarios/mariadb-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/mariadb-scenario/src/main/resources/application.yaml
new file mode 100644
index 0000000..cb7ac89
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/src/main/resources/application.yaml
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+server:
+  port: 8080
+  servlet:
+    context-path: /mariadb-scenario
+logging:
+  config: classpath:log4j2.xml
diff --git a/test/plugin/scenarios/mariadb-scenario/src/main/resources/jdbc.properties b/test/plugin/scenarios/mariadb-scenario/src/main/resources/jdbc.properties
new file mode 100644
index 0000000..c494405
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/src/main/resources/jdbc.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+mariadb.url=jdbc:mariadb://mariadb-server:3306/test
+mariadb.username=root
+mariadb.password=root
diff --git a/test/plugin/scenarios/mariadb-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/mariadb-scenario/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..b5cda5a
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/src/main/resources/log4j2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<Configuration status="WARN">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_ERR">
+            <PatternLayout charset="UTF-8" pattern="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="WARN">
+            <AppenderRef ref="Console"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/test/plugin/scenarios/mariadb-scenario/support-version.list b/test/plugin/scenarios/mariadb-scenario/support-version.list
new file mode 100644
index 0000000..693cd2b
--- /dev/null
+++ b/test/plugin/scenarios/mariadb-scenario/support-version.list
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# lists your version here
+
+2.6.0
+2.5.4
+2.4.4
+2.3.0
+2.2.6
+2.1.2
+2.0.3
+1.8.0
+