MariaDB Connector/J is our widely used Type 4 JDBC driver for Java. This session covers the basics of getting started with Java and MariaDB, and moves quickly to more advanced topics, including connection pooling, automatic failover and debugging. Diego Dupin also includes an overview of popular object/relational mapping (ORM) and programming frameworks for Java. Even if you have been using the MariaDB Connector/J for years, come to this session to learn about the latest release, see where the connector is going and discover the latest tips and tricks.
3. MARIADB JAVA CONNECTOR
MariaDB is 100% java driver, initially fork from drizzle
JDBC 4.2 compliant
First release 2012
400K DL per month (maven stats)
4. JAVA CONNECTOR
Why not using MySQL connector ?
● MariaDB specific implementation
○ Bulk batch
○ Authentication (GSSAPI, ed25519 …)
● Performance : exemple on query “SELECT * FROM mysql.user”
13. SSL - one way authentication
Server must be configured for SSL (yassl/openssl)
One-Way SSL Authentication .
Not reusing context
try (Connection con =
DriverManager.getConnection("jdbc:mariadb://localhost/myDb?user=myUser&password=MyPwd&useSSL=true”)) {
try (Statement stmt = con.createStatement()) {
stmt.execute("select 1");
}
}
CREATE USER 'myUser'@'%' IDENTIFIED BY 'MyPwd';
GRANT ALL ON db_name.* TO 'myUser'@'%' REQUIRE SSL;
14. SSL - mutual authentication
Server must be configured for SSL (yassl/openssl)
mutual SSL Authentication .
try (Connection con =
DriverManager.getConnection("jdbc:mariadb://localhost/myDb?user=myUser&password=MyPwd&useSSL=true&clientCertificateKe
yStoreUrl=/tmp/…”
)) {
try (Statement stmt = con.createStatement()) {
stmt.execute("select 1");
}
}
CREATE USER 'myUser'@'%' IDENTIFIED BY 'MyPwd';
GRANT ALL ON db_name.* TO 'myUser'@'%' REQUIRE X509;
15. SSL - some options
useSSL Force SSL/TLS on connection.
trustServerCertificate When using SSL/TLS, do not check server's certificate.
serverSslCert Permits providing server's certificate in DER form, or server's CA certificate.
keyStore File path of the keyStore file that contain client private key store and associate certificates
keyStorePassword Password for the client certificate keyStore
trustStore File path of the trustStore file (similar to java System property "javax.net.ssl.trustStore").
trustStorePassword Password for the trusted root certificate file (similar to java System property "javax.net.ssl.trustStorePassword").
enabledSslProtocolSuites Force TLS/SSL protocol to a specific set of TLS versions (comma separated list).
enabledSslCipherSuites Indicate permited ciphers
disableSslHostnameVerification checks the hostname against the server's identity as presented in the server's certificate
keyStoreType Indicate key store type (JKS/PKCS12). default is null, then using java default type.
trustStoreType Indicate trust store type (JKS/PKCS12). default is null, then using java default type.
17. POOLING
Basically a database connection cache implementation
Connections are expensive. On local DB:
● 2.4ms for a basic connection
● 0.05ms for a simple query
Problem : correctness and reliability
18. POOLING
Lots of pools : apache dbcp2, HikariCP, c3p0
Best is HikariCP :
● Good default
● Widely used
● Very fast
● Show connection leaks
● Doesn’t always validate connection (500ms)
● Reliable :
○ Readonly, autocommit, isolation, schema, network timeout reset
○ rollback
● Pool handle connection creation in dedicated thread
19. POOLING
- Implementation to handle query pikes
Example with a pool that is configured to have a maximum of 50 connections. actual
connection number is 5.
With a basis of a connection creation taking 2.4ms, and query taking 0.05ms (example
on a local server).
Everything is quiet, and then ... Boom! ... 100 queries on the pool at once, wanting a
connection.
22. POOLING
● Good for failover recovery
Just
● configure “maxLifetime” option according to Server @@wait_timeout
● Don’t set “connectionTestQuery” option
● Avoid setting “minimumIdle” option
● If always disabling autocommit (hibernate):
○ autoCommit option to false
○ "jdbc:mariadb://localhost/db?user=user&sessionVariables=autocommit=0";
23. POOLING
Connection pools SIZING error
Example 10 000 user simultaneously, 20 000 transaction per second.
What value to connectionLimit (max connection number in pool) ?
100 ? 500 ? 1000 ?
25. Streaming
Goal : Avoid loading all in memory
● Streaming resultset -> avoiding loading large resultset totally into memory
● Streaming sent -> sending buffer by chunk
26. Streaming resultset
Limitations :
● Server net_write_timeout.
○ For a command: SET STATEMENT net_write_timeout=10000 FOR XXX
○ For a connection: ”&sessionVariables=net_write_timeout=31536000”
stmt.setFetchSize(100);
ResultSet rs = stmt.executeQuery("SELECT charValue FROM
testBatchString");
int counter = 0;
while (rs.next()) {
System.out.println(rs.getString(1));
}
27. Streaming - sending
try (FileInputStream fis = new FileInputStream(tmpFile)) {
try (PreparedStatement ps = sharedConnection.prepareStatement("insert into bigblob
values(?)")) {
ps.setCharacterStream(1, new InputStreamReader(fis, StandardCharsets.UTF_8));
ps.executeUpdate();
}
}
Limitations :
● Server net_read_timeout
● max_allowed_packet
31. MULTI-HOST
load balancing and high availability
jdbc:mariadb:[replication:|failover:|sequential:]//<hostDescription>[,<hostDescription>...]/[database][?<key1>=<
value1>[&<key2>=<value2>]]
Sequential multi-master with failover support, always using in sequence until fails
Failover multi-master with failover support
Replication multi-master + multi-slave with failover support
34. MULTI-HOST
Using standard JDBC
try {Connection conn =
DriverManager.getConnection("jdbc:mysql:replication://master1,slave1/db?user=root")) {
Statement stmt = conn.createStatement();
stmt.execute("SELECT 1"); // will execute query on the underlying master1 connection
conn.setReadOnly(true);
stmt.execute("SELECT 1"); // will execute query on the underlying slave1 connection
}
35. MULTI-HOST
Using Hibernate
Using Spring data jpa : automatic findxxx() automatically setReadOnly(true)
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public void createUser(EntityManager em) {
User user = new User("Jean claude", "Van Damme");
em.persist(user);
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public User findUser(EntityManager em, Integer id) {
return em.find(User.class, id);
}
37. SPRING DATA JPA
Spring data JPA is the actual reference in java.
Need configuration for optimisation. Example with :
repository.save(new User("Jack", "Bauer"));
repository.save(new User("Chloe", "O'Brian"));
List<User> users = new ArrayList();
users.add(new User("Kim", "Bauer"));
users.add(new User("David", "Palmer"));
users.add(new User("Michelle", "Dessler"));
Iterable<User> savedUsers = repository.saveAll(users);
savedUsers.forEach(user -> {
System.out.println(user);
});
public class User {
public User(String lastName, String firstName) {
this.lastName = lastName;
this.firstName = firstName;
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String lastName;
private String firstName;
}
38. SPRING DATA JPA
set autocommit=0
set autocommit=0
select next_val as id_val from hibernate_sequence for update
update hibernate_sequence set next_val= ? where next_val=?, parameters [2,1]
COMMIT
set autocommit=1
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Jack',1]
COMMIT
set autocommit=1
set autocommit=0
set autocommit=0
select next_val as id_val from hibernate_sequence for update
update hibernate_sequence set next_val= ? where next_val=?, parameters [3,2]
COMMIT
set autocommit=1
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['O'Brian','Chloe',2]
COMMIT
set autocommit=1
set autocommit=0
set autocommit=0
select next_val as id_val from hibernate_sequence for update
update hibernate_sequence set next_val= ? where next_val=?, parameters [4,3]
COMMIT
set autocommit=1
set autocommit=0
select next_val as id_val from hibernate_sequence for update
39. SPRING DATA JPA
With HikariCP configured with autocommit : false and adding “autocommit=0” to connection string
(dialect MySQL5Dialect)
select next_val as id_val from hibernate_sequence for update
update hibernate_sequence set next_val= ? where next_val=?, parameters [2,1]
COMMIT
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Jack',1]
COMMIT
select next_val as id_val from hibernate_sequence for update
update hibernate_sequence set next_val= ? where next_val=?, parameters [3,2]
COMMIT
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['O'Brian','Chloe',2]
COMMIT
select next_val as id_val from hibernate_sequence for update
update hibernate_sequence set next_val= ? where next_val=?, parameters [4,3]
COMMIT
select next_val as id_val from hibernate_sequence for update
update hibernate_sequence set next_val= ? where next_val=?, parameters [5,4]
COMMIT
select next_val as id_val from hibernate_sequence for update
update hibernate_sequence set next_val= ? where next_val=?, parameters [6,5]
COMMIT
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Kim',3]
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Palmer','David',4]
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Dessler','Michelle',5]
COMMIT
40. SPRING DATA JPA
With HikariCP configured with autocommit : false and adding “autocommit=0” to connection string
(dialect MariaDB103Dialect)
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Jack',1]
COMMIT
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['O'Brian','Chloe',2]
COMMIT
select nextval(hibernate_sequence)
select nextval(hibernate_sequence)
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Kim',3]
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Palmer','David',4]
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Dessler','Michelle',5]
COMMIT
41. SPRING DATA JPA
Changing default strategy auto to native :
public class User {
public User(String lastName, String firstName) {
this.lastName = lastName;
this.firstName = firstName;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
private Integer id;
private String lastName;
private String firstName;
}
42. SPRING DATA JPA
With HikariCP configured with autocommit : false and adding “autocommit=0” to connection string
(dialect MariaDB103Dialect + strategy native)
insert into User (firstName, lastName) values (?, ?), parameters ['Bauer','Jack']
COMMIT
insert into User (firstName, lastName) values (?, ?), parameters ['O'Brian','Chloe']
COMMIT
insert into User (firstName, lastName) values (?, ?), parameters ['Bauer','Kim']
insert into User (firstName, lastName) values (?, ?), parameters ['Palmer','David']
insert into User (firstName, lastName) values (?, ?), parameters ['Dessler','Michelle']
COMMIT
43. SPRING DATA JPA
With HikariCP configured with autocommit : false and adding “autocommit=0” to connection string
(dialect MariaDB103Dialect)
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Jack',1]
COMMIT
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['O'Brian','Chloe',2]
COMMIT
select nextval(hibernate_sequence)
select nextval(hibernate_sequence)
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Kim',3]
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Palmer','David',4]
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Dessler','Michelle',5]
COMMIT
44. SPRING DATA JPA
With HikariCP configured with autocommit : false and adding
“&sessionVariables=autocommit=0&useBulkStmts&rewriteBatchedStatements” to connection string
(dialect MariaDB103Dialect)
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Jack',1]
COMMIT
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['O'Brian','Chloe',2]
COMMIT
select nextval(hibernate_sequence)
select nextval(hibernate_sequence)
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Kim',3]
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Palmer','David',4]
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Dessler','Michelle',5]
COMMIT
45. SPRING DATA JPA
using sequence in pool:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@GenericGenerator(
name = "sequenceGenerator",
strategy = "enhanced-sequence",
parameters = {
@org.hibernate.annotations.Parameter(
name = "optimizer",
value = "pooled"
),
@org.hibernate.annotations.Parameter(
name = "initial_value",
value = "1"
),
@org.hibernate.annotations.Parameter(
name = "increment_size",
value = "5"
)
}
)
private Integer id;
46. SPRING DATA JPA
With HikariCP configured with autocommit : false and adding
“&sessionVariables=autocommit=0&useBulkStmts&rewriteBatchedStatements” to connection string
(dialect MariaDB103Dialect)
select nextval(hibernate_sequence)
select nextval(hibernate_sequence)
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Jack',1]
COMMIT
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['O'Brian','Chloe',2]
COMMIT
insert into User (firstName, lastName, id) values (?, ?, ?), parameters ['Bauer','Kim',3],['Palmer','David',4],['Dessler','Michelle',5]
COMMIT