Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support MySQL safe updates mode in MySQLMaxValueIncrementer #26858

Closed
slankka opened this issue Apr 24, 2021 · 1 comment
Closed

Support MySQL safe updates mode in MySQLMaxValueIncrementer #26858

slankka opened this issue Apr 24, 2021 · 1 comment
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement
Milestone

Comments

@slankka
Copy link

slankka commented Apr 24, 2021

Affects: all


Hi~
I found a small problem while using Spring Batch. I , it would be better that spring-jdbc's MySQLMaxValueIncrementer supports MYSQL safe_update_mode (or safe mode)

Mysql safe_update Mode

First if we have a MySQL database instance with global option:

SET global sql_safe_updates=1

Then the 'Incrementer' will fail:

Exception in thread "main" org.springframework.dao.DataAccessResourceFailureException: 
Could not increment value for tab_sequence sequence table; 
nested exception is java.sql.SQLException: 
You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. 
	at org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer.getNextKey(MySQLMaxValueIncrementer.java:148)
	at org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer.nextIntValue(AbstractDataFieldMaxValueIncrementer.java:123)

Code from spring-jdbc

stmt.executeUpdate("update " + getIncrementerName() + " set " + columnName +
" = last_insert_id(" + columnName + " + " + getCacheSize() + ")");

As Mysql Reference says:

Enabling sql_safe_updates causes UPDATE and DELETE statements to produce an error if they do not specify a key constraint in the WHERE clause, or provide a LIMIT clause, or both.

Solution

If we add limit 1, then this statement will success.

stmt.executeUpdate("update " + getIncrementerName() + " set " + columnName +
" = last_insert_id(" + columnName + " + " + getCacheSize() + ") limit 1");

or turn off sql_safe_updates (may be ignored by some dba middleware )

stmt.execute("SET sql_safe_updates=0;");
stmt.executeUpdate("update " + getIncrementerName() + " set " + columnName +
" = last_insert_id(" + columnName + " + " + getCacheSize() + ")");

or

stmt.executeUpdate("update " + getIncrementerName() + " set " + columnName +
" = last_insert_id(" + columnName + " + " + getCacheSize() + ") where id >=0 ");

Spring Batch

Here are some schema in Spring Batch project.

https://github.com/spring-projects/spring-batch/blob/master/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mysql.sql

for example

CREATE TABLE BATCH_STEP_EXECUTION_SEQ (
	ID BIGINT NOT NULL,
	UNIQUE_KEY CHAR(1) NOT NULL,
	constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
) ENGINE=InnoDB;

The ID column neither is a primary key, nor a indexed column. The safe_update_mode will raise an exception.

Appendix

A quick test code:

@SpringBootApplication
public class JdbcSafemodeApplication {

	@Bean
	public JdbcTemplate JdbcTemplate(DataSource dataSource) {
		return new JdbcTemplate(dataSource);
	}

	@Bean
	public MySQLMaxValueIncrementer incrementer(DataSource dataSource) {
		return new MySQLMaxValueIncrementer(dataSource, "tab_sequence", "value");
	}

	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(JdbcSafemodeApplication.class, args);
		JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);

//		jdbcTemplate.execute("insert into tab_sequence values(0);");

//		MySQLMaxValueIncrementer incrementer = context.getBean(MySQLMaxValueIncrementer.class);
//		int i = incrementer.nextIntValue();

		jdbcTemplate.execute("SET sql_safe_updates=0;");
		jdbcTemplate.execute("update tab_sequence set value = 3;");
	}
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 24, 2021
@sbrannen sbrannen added the in: data Issues in data modules (jdbc, orm, oxm, tx) label Apr 27, 2021
@sbrannen sbrannen changed the title Mysql safe_update support for MySQLMaxValueIncrementer advice Support MySQL sql_safe_updates in MySQLMaxValueIncrementer Apr 27, 2021
@sbrannen sbrannen changed the title Support MySQL sql_safe_updates in MySQLMaxValueIncrementer Support MySQL safe updates mode in MySQLMaxValueIncrementer Apr 28, 2021
@sbrannen sbrannen added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 29, 2021
@sbrannen sbrannen added this to the 5.3.7 milestone Apr 29, 2021
@sbrannen
Copy link
Member

Hi @slankka,

Thanks for creating your first issue for the Spring Framework!

We have decided to go with your limit 1 proposal for inclusion in Spring Framework 5.3.7.

@sbrannen sbrannen self-assigned this Apr 29, 2021
Zoran0104 pushed a commit to Zoran0104/spring-framework that referenced this issue Aug 20, 2021
Prior to this commit, MySQLMaxValueIncrementer could not be used when
the MySQL database was configured to use safe-updates mode.

See https://dev.mysql.com/doc/refman/8.0/en/mysql-tips.html#safe-updates

This commit introduces a `limit 1` clause to the generated update
statement to allow MySQLMaxValueIncrementer to be compatible with
MySQL safe-updates mode.

Closes spring-projectsgh-26858
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
Prior to this commit, MySQLMaxValueIncrementer could not be used when
the MySQL database was configured to use safe-updates mode.

See https://dev.mysql.com/doc/refman/8.0/en/mysql-tips.html#safe-updates

This commit introduces a `limit 1` clause to the generated update
statement to allow MySQLMaxValueIncrementer to be compatible with
MySQL safe-updates mode.

Closes spring-projectsgh-26858
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants