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.