spring-projects / spring-projects/spring-session

Deadlock in SQL Server when INSERT INTO SPRING_SESSION_ATTRIBUTES by JdbcOperationsSessionRepository

Open
#1,550 16 comments 2 reactions 2 assignees View on GitHub

@vpavic is already working on this.

Since Jun 23, 2020.

in: jdbc type: bug
Dominant language
Java
Stars
1.9k
Forks
1.2k
Avg merge
4h 27m
Merged PRs (30d)
55

Description

I have a deadlock in SQL Server.

LOG

Forwarding to error page from request [/login] due to exception [PreparedStatementCallback; SQL [INSERT INTO SPRING_SESSION_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) SELECT PRIMARY_ID, ?, ? FROM SPRING_SESSION WHERE SESSION_ID = ?]; ***deadlock error message from sql server is omitted because Japanese language***
org.springframework.dao.DeadlockLoserDataAccessException: PreparedStatementCallback; SQL [INSERT INTO SPRING_SESSION_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) SELECT PRIMARY_ID, ?, ? FROM SPRING_SESSION WHERE SESSION_ID = ?]; ***deadlock error message from sql server is omitted because Japanese language***
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:266)
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
	at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1442)
	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:632)
	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:861)
	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:916)
	at org.springframework.session.jdbc.JdbcOperationsSessionRepository.insertSessionAttributes(JdbcOperationsSessionRepository.java:548)
	at org.springframework.session.jdbc.JdbcOperationsSessionRepository.access$300(JdbcOperationsSessionRepository.java:135)

I read all the previous issues about this problem.

As #1083 @TorosyanV said:

we need to always keep order to avoid deadlock on parent and child relationship table's operation.

like as below:

parnet = SPRING_SESSION
child = SPRING_SESSION_ATTRIBUTES

insert parent first, then child
update parent first, then child
delete parent first, then child
select parent first, then child

I looked at the JdbcOperationsSessionRepository code,
and I understood it looks like keeping transaction order.

but major problem here is DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY is depending on each relational database's CASCADE ON DELETE algorithm
which might not be the same order deleting parent and child.
and also, we are difficult position to know or change relational database's CASCADE ON DELETE algorithm.

It is better not rely on to database's CASCADE ON DELETE.
I wish, Spring framework will ensure the every session table's transaction operation order by own.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.