[MXS-3980] readwritesplit not understanding SET SESSION TRANSACTION READ ONLY Created: 2022-02-02  Updated: 2022-02-24  Resolved: 2022-02-24

Status: Closed
Project: MariaDB MaxScale
Component/s: Core
Affects Version/s: 6.2.1
Fix Version/s: N/A

Type: Bug Priority: Major
Reporter: Olof Larsson Assignee: markus makela
Resolution: Duplicate Votes: 0
Labels: None

Issue Links:
Relates
relates to MXS-185 "read-only" transactions to be direct... Closed
relates to MXS-3769 SET TRANSACTION READ ONLY not detected Closed
relates to MXS-3947 Read-only transaction behavior is not... Closed

 Description   

In Short
The readwritesplit module fails to send read only transactions to slaves if created by SET SESSION TRANSACTION READ ONLY.

How to Reproduce
The problem can be reproduced as follows.

  1. Check out https://github.com/mariadb-corporation/maxscale-docker/tree/master/maxscale
  2. Change to :latest tags.
  3. Do docker-compose up.
  4. Connect with mysql client to port 4006 (the readwrite port)
  5. Execute "SET SESSION TRANSACTION READ ONLY;"
  6. Execute "SET autocommit=0;" or "START TRANSACTION;"
  7. Execute "SELECT @@hostname;" multiple times
  8. Note how the one and same host shows up.
  9. Terminal command "docker ps" to see that the hostname is the master node.

In this case I expected to see different slave hostnames show up because that would mean the read only transaction was executed on a slave.

Use Case and Clarification
If the transaction is started with START TRANSACTION READ ONLY it will be properly sent to slaves. This is however not always possible.

In my concrete use case I'm developing a Spring Boot application with Hibernate and mariadb-connector/j. I want to leverage the slave nodes in read only transactions created with the @Transactional(readOnly=true) Spring Boot annotation.

Hibernate starts transactions via JDBC using SET autocommit=0; and can not be instructed to start them using START TRANSACTION READ ONLY. We can however make the mariadb-connector/j start read only connections using a JDBC url like: jdbc:mariadb:replication://maxscale:3306,maxscale:3306/databasename?assureReadOnly=true. So by using replication mode, repeating host:port twice and using assureReadOnly=true Hibernate properly uses connections that were started with SET SESSION TRANSACTION READ ONLY in situations where @Transactional(readOnly=true) Spring annotations were used.

I have checked with wireshark and the end result of queries sent by Hibernate goes something like:
SET SESSION TRANSACTION READ ONLY;
SET AUTOCOMMIT=0
SELECT @@hostname;

It would be great if MaxScale supported this. A potential workaround would be to set up a second read only listener, but it would be great not having to do that.

Reflection
Hibernate will always open a transaction. Even when reading, but that makes sense from a data integrity perspective since the object relational mapping work often takes multiple select statements.

I think SpringBoot + Hibernate is a reasonably common usecase. A usecase that MaxScale does not seem to support well at all. What happens is that for pretty much all configurations all traffic will just go to the master node.



 Comments   
Comment by markus makela [ 2022-02-02 ]

This seems like a duplicate of MXS-3769 which is fixed for MaxScale 7.

Comment by Olof Larsson [ 2022-02-02 ]

That sounds promising. Is there a Docker image available that I can use to try and verify?

I only find up to version 6 on https://hub.docker.com/r/mariadb/maxscale/tags?

Is 7 not yet released? Is there a planned release date?

Comment by markus makela [ 2022-02-02 ]

Version 7 is still in development. If you'd like to give it a try, you could try to compile it from source, it's currently on the develop branch on GitHub.

Comment by markus makela [ 2022-02-24 ]

I'm going to close this as a duplicate of MXS-3769. If you manage to build MaxScale from source and find any problems with the implemented fix, please open separate tickets for those issues.

Comment by Olof Larsson [ 2022-02-24 ]

I think you are right. This is a duplicate of that ticket.

I'll not be building MaxScale because we can't use it in production anyways. Instead we opened a second port and made use of a more advanced JDBC url.

If you are interested in more details I wrote a post about it: https://olof.tech/transactional-readonly-true-with-hibernate-maxscale-and-galera/

Comment by markus makela [ 2022-02-24 ]

That's pretty cool, I'll check it out.

Generated at Thu Feb 08 04:25:20 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.