Skip to main content

Upserts with version awareness in a relational database - Part Two: MariaDB / MySQL

Insert, or Conditional Update 

I started off trying out MariaDB as a comparison to how PostgreSQL supports upserts with version awareness.  MariaDB started off as a fork of MySQL, so it makes sense that the same approach is also applicable to MySQL. 

From part one of this blog post series, we have a simple table definition:

CREATE TABLE event (id UUID PRIMARY KEY, 
name varchar(255) NOT NULL,
version bigint NOT NULL DEFAULT 0)

Unlike PostgreSQL, we don't have:

ON CONFLICT

as a clause to fall back from insert to update.

Instead there is:

ON DUPLICATE

that can be applied as follows (once again, the syntax is JDBC, where each '?' character represents a value that is passed in at runtime):

INSERT INTO event (id, name, version) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE
name = (IF(version < VALUES(version), VALUES(name), name)),
version = (IF(version < VALUES(version), VALUES(version), version))

Stylistically it doesn't seem like a scalable approach that I would want to apply for a table that has more attributes, as we have to specify the version clause on each individual property. I would prefer it if we could specify a where clause to guard the update, but that is not available. 

An anomaly in rows affected? 

Normally when we use executeUpdate on a JDBC Statemenbt we receive back a response that is the row count of the number of rows that were added or altered by the statement. In this situation there is different behaviour, as documented on the MariaDB website. Basically an insert is represented by the value 1, and an update is represented by the value 2 (Sidenote: this is something ChatGPT does not seem to be aware of, as it takes a literal approach to the actual number of rows affected).

I thought that the rows affected values would be useful for being able to keep track of the relative frequencies of inserts versus updates, until I noticed something odd when running some tests...

It seems that when the update is only setting the existing values then the rows affected value that will be returned is 1, making that situation indistinguishable from the insert.

Update

Based on this documentation it seems that we have an explanation for why the update can return rows affected as being 1, "existing row is set to its current values, and the CLIENT_FOUND_ROWS is set".

If I change my JDBC Connection setup to specify the non-default value for useAffectedRows then we get a 1 when an insert occurs, a 2 when an update changes the existing record, and a 0 when the update is setting the values to be the same as the existing state.

Properties properties = new Properties();
properties.put("user", DB_USER);
properties.put("password", PASSWORD);

properties.put("useAffectedRows", true);

Connection connection = DriverManager.getConnection(jdbcUrl, properties);

Disclaimer

The approach shared in this post is not something that I am offering up as a recommended or optimal way to get conditional logic applied when upserting into MariaDB or MySQL.

It's more a case of me thinking aloud, because thinking is allowed.  

Comments

Popular posts from this blog

Speeding up Software Builds for Continuous Integration

Downloading the Internet Can you remember the last time you started out on a clean development environment and ran the build of some software using Maven or Gradle for dependency management? It takes ages to download all of the necessary third party libraries from one or more remote repositories, leading to expressions like, "Just waiting for Maven to download the Internet". Once your development environment has been used for building a few projects the range of dependencies that will need to be downloaded for other builds reduces down as the previously referenced ones will now be cached and found locally on your computer's hard drive. What happens on the Continuous Integration environment? Now consider what goes on when Jenkins or your other preferred Continuous Integration server comes to build your software. If it doesn't have a local copy of the libraries that have been referenced then it is going to pay the cost of that slow " download the Internet" p...

2022 - A year in review

Just a look back over the last 12 months. January I moved back to Christchurch to live, after having spent a few months further south since moving back from London. Work was mainly around balancing other peoples' understanding and expectations around our use of Kafka. February I decided that it would be worthwhile to have a year's subscription for streaming Sky Sports, as some rugby matches that I would want to watch would be on at time when venues wouldn't be open. Having moved to Christchurch to be close to an office, now found myself working from home as Covid restrictions came back into effect across New Zealand. March Got back into some actual coding at work - as opposed to mainly reviewing pull requests for configuration changes for Kafka topics.  This became urgent, as the command line interface tool that our provisioning system was dependent on had been marked for deprecation. April   Had my first direct experience with Covid-19.  I only went for a test because ...

Applying AI to software development can be like following SatNav

Trying out a different navigation system A month or so ago I upgraded to a car that has a SatNav system included, so I have been trying to use that instead of the Maps app on my phone. My experiences with it so far have generally been good, but it is far from flawless - a bit like Artificial Intelligence (AI) in software development. As context, my previous vehicle was not too old to include SatNav, it just hadn't been set up with English language or New Zealand maps - one of the down sides of having a second hand vehicle that originated in Japan. Flawed or incomplete information Driving around central Christchurch can be a bit challenging at times as various roadworks are underway, leaving streets closed off or narrowed down to a single lane. It could be reasonable to expect that a basic navigation system might not have up to the minute awareness of those closures and restrictions. However, something that I did not expect to encounter was the navigation system advising me to expec...