PessimisticLockingFailureException Issue (feat.Concurrency)

Feb 03, 2024
PessimisticLockingFailureException Issue (feat.Concurrency)

โ“Business Context


CQRS๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๊ธฐ๋Šฅ๋“ค์— ๋Œ€ํ•ด 2500 ๊ฑด์˜ ๋ถ€ํ•˜์Šค๋ ˆ๋“œ๋ฅผ ๋Œ๋ ค๋ณด์•˜๋‹ค.
  • ์ƒํ’ˆ ์ „์ฒด ์กฐํšŒ
  • ๊ตฌ๋งค์ž…์ฐฐ ๋“ฑ๋ก
 
๊ทธ๋Ÿฌ๋˜ ์ค‘,,,๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค,,,
notion image
notion image
 
์™œ์ผ๊นŒ?
์„ธ๋ถ€ ์—๋Ÿฌ ์ฝ”๋“œ
2024-02-01T11:50:18.263Z INFO 1 --- [o-8080-exec-226] Redis Util : [hasKey] hasKey : true 2024-02-01T11:50:18.263Z INFO 1 --- [o-8080-exec-226] JWT authorization : ์ธ์ฆ ์ฒ˜๋ฆฌ [Hibernate] select u1_0.`id`, u1_0.`created_at`, u1_0.`login_id`, u1_0.`modified_at`, u1_0.`nickname`, u1_0.`oauth_id`, u1_0.`password`, u1_0.`point`, u1_0.`provider`, u1_0.`role` from `tb_user` u1_0 where u1_0.`login_id`=? [Hibernate] select p1_0.`id`, p1_0.`brand`, p1_0.`created_at`, p1_0.`description`, p1_0.`image_url`, p1_0.`modified_at`, p1_0.`name`, p1_0.`price` from `tb_product` p1_0 where p1_0.`id`=? [Hibernate] select p1_0.`id`, p1_0.`brand`, p1_0.`created_at`, p1_0.`description`, p1_0.`image_url`, p1_0.`modified_at`, p1_0.`name`, p1_0.`price` from `tb_product` p1_0 where p1_0.`id`=? [Hibernate] update `tb_user` set `login_id`=?, `modified_at`=?, `nickname`=?, `oauth_id`=?, `password`=?, `point`=?, `provider`=?, `role`=? where `id`=? 2024-02-01T11:50:18.250Z WARN 1 --- [o-8080-exec-223] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1213, SQLState: 40001 2024-02-01T11:50:18.267Z ERROR 1 --- [o-8080-exec-223] o.h.engine.jdbc.spi.SqlExceptionHelper : Deadlock found when trying to get lock; try restarting transaction 2024-02-01T11:50:18.257Z WARN 1 --- [o-8080-exec-213] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1213, SQLState: 40001 2024-02-01T11:50:18.268Z ERROR 1 --- [o-8080-exec-213] o.h.engine.jdbc.spi.SqlExceptionHelper : Deadlock found when trying to get lock; try restarting transaction 2024-02-01T11:50:18.232Z ERROR 1 --- [o-8080-exec-220] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.CannotAcquireLockException: could not execute statement [Deadlock found when trying to get lock; try restarting transaction] [update `tb_user` set `login_id`=?,`modified_at`=?,`nickname`=?,`oauth_id`=?,`password`=?,`point`=?,`provider`=?,`role`=? where `id`=?]; SQL [update `tb_user` set `login_id`=?,`modified_at`=?,`nickname`=?,`oauth_id`=?,`password`=?,`point`=?,`provider`=?,`role`=? where `id`=?]] with root cause com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:124) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1061) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1009) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1320) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:994) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java) ~[HikariCP-5.0.1.jar!/:na] at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:275) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.performNonBatchedMutation(AbstractMutationExecutor.java:107) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleNonBatched.performNonBatchedOperations(MutationExecutorSingleNonBatched.java:40) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:52) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.doStaticUpdate(UpdateCoordinatorStandard.java:771) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.performUpdate(UpdateCoordinatorStandard.java:327) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.coordinateUpdate(UpdateCoordinatorStandard.java:244) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2753) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:166) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:635) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:502) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:364) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1412) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:485) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2301) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1966) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:169) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:267) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:561) ~[spring-orm-6.0.15.jar!/:6.0.15] at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:660) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:410) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.15.jar!/:6.0.15] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) ~[spring-aop-6.0.15.jar!/:6.0.15] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703) ~[spring-aop-6.0.15.jar!/:6.0.15] at bc1.gream.domain.buy.provider.BuyBidProvider$$SpringCGLIB$$0.buyBidProduct(<generated>) ~[classes!/:0.0.1-SNAPSHOT] at bc1.gream.domain.buy.controller.BuyBidController.buyBidProduct(BuyBidController.java:46) ~[classes!/:0.0.1-SNAPSHOT] at jdk.internal.reflect.GeneratedMethodAccessor123.invoke(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) ~[spring-web-6.0.15.jar!/:6.0.15] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) ~[spring-web-6.0.15.jar!/:6.0.15] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) ~[spring-web-6.0.15.jar!/:6.0.15] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at bc1.gream.global.jwt.JwtAuthFilter.doFilterInternal(JwtAuthFilter.java:63) ~[classes!/:0.0.1-SNAPSHOT] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at bc1.gream.global.exception.ExceptionHandlerFilter.doFilterInternal(ExceptionHandlerFilter.java:24) ~[classes!/:0.0.1-SNAPSHOT] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) ~[spring-security-web-6.1.6.jar!/:6.1.6] at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$3(HandlerMappingIntrospector.java:195) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:225) ~[spring-security-config-6.1.6.jar!/:6.1.6] at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268) ~[spring-web-6.0.15.jar!/:6.0.15] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:109) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:186) ~[spring-orm-6.0.15.jar!/:6.0.15] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.15.jar!/:6.0.15] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.17.jar!/:na] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-10.1.17.jar!/:na] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na] 2024-02-01T11:50:18.285Z INFO 1 --- [io-8080-exec-11] JWT authorization : accessToken : null 2024-02-01T11:50:18.285Z INFO 1 --- [o-8080-exec-203] JWT authorization : accessToken : null 2024-02-01T11:50:18.286Z INFO 1 --- [o-8080-exec-219] JWT authorization : accessToken : null 2024-02-01T11:50:18.246Z ERROR 1 --- [o-8080-exec-217] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.CannotAcquireLockException: could not execute statement [Deadlock found when trying to get lock; try restarting transaction] [update `tb_user` set `login_id`=?,`modified_at`=?,`nickname`=?,`oauth_id`=?,`password`=?,`point`=?,`provider`=?,`role`=? where `id`=?]; SQL [update `tb_user` set `login_id`=?,`modified_at`=?,`nickname`=?,`oauth_id`=?,`password`=?,`point`=?,`provider`=?,`role`=? where `id`=?]] with root cause com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:124) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1061) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1009) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1320) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:994) ~[mysql-connector-j-8.0.33.jar!/:8.0.33] at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java) ~[HikariCP-5.0.1.jar!/:na] at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:275) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.performNonBatchedMutation(AbstractMutationExecutor.java:107) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleNonBatched.performNonBatchedOperations(MutationExecutorSingleNonBatched.java:40) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:52) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.doStaticUpdate(UpdateCoordinatorStandard.java:771) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.performUpdate(UpdateCoordinatorStandard.java:327) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard.coordinateUpdate(UpdateCoordinatorStandard.java:244) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2753) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:166) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:635) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:502) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:364) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1412) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:485) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2301) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1966) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:169) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:267) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-6.2.17.Final.jar!/:6.2.17.Final] at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:561) ~[spring-orm-6.0.15.jar!/:6.0.15] at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:660) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:410) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-6.0.15.jar!/:6.0.15] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.15.jar!/:6.0.15] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) ~[spring-aop-6.0.15.jar!/:6.0.15] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703) ~[spring-aop-6.0.15.jar!/:6.0.15] at bc1.gream.domain.buy.provider.BuyBidProvider$$SpringCGLIB$$0.buyBidProduct(<generated>) ~[classes!/:0.0.1-SNAPSHOT] at bc1.gream.domain.buy.controller.BuyBidController.buyBidProduct(BuyBidController.java:46) ~[classes!/:0.0.1-SNAPSHOT] at jdk.internal.reflect.GeneratedMethodAccessor123.invoke(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.0.15.jar!/:6.0.15] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[spring-webmvc-6.0.15.jar!/:6.0.15]

๐Ÿ“ Test Code ๋กœ ๋™์ผํ•œ ์ƒํ™ฉ์„ ๋งŒ๋“ค์–ด๋ณด์ž


ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋กœ ๋™์ผํ•œ ์ƒํ™ฉ์„ ๋งŒ๋“  ํ›„, try-catch ๋ฅผ ํ†ตํ•ด ์–ด๋–ค ์˜ˆ์™ธ๋ฅผ ๋ฟœ๋Š”์ง€ ์‚ดํŽด๋ณด์•˜๋‹ค.
๋งŒ๋“ค๊ณ ์žํ•˜๋Š” ์ƒํ™ฉ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค. ( JMeter์—์„œ์˜ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค์™€ ๋™์ผํ•˜๋‹ค )
ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค
  • 2500๊ฐœ์˜ ์Šค๋ ˆ๋“œ
  • ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์•„๋ž˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœ
    • ์ƒํ’ˆ ์ „์ œ ์กฐํšŒ
    • ๋กœ๊ทธ์ธํ•œ ์œ ์ €์˜ ๊ตฌ๋งค์ž…์ฐฐ ์ƒ์„ฑ ์š”์ฒญ
 
์ด์— ๋”ฐ๋ผ ์•„๋ž˜์™€ ๊ฐ™์ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.
@SpringBootTest @WithMockCustomUser @ActiveProfiles("test") public class DeadlockTest extends BaseIntegrationTest { @Autowired private TransactionTemplate transactionTemplate; @Autowired private ProductService productService; @Autowired private BuyBidProvider buyBidProvider; @BeforeEach void setUp() { setUpBaseIntegrationTest(); } @AfterEach void tearDown() { tearDownBaseIntegrationTest(); } @Test @Transactional public void ์Šค๋ ˆ๋“œ2500๊ฐœ_๋™์‹œ์—_๊ตฌ๋งค์ž…์ฐฐ์ƒ์„ฑ์š”์ฒญ() throws InterruptedException, ExecutionException { // GIVEN BuyBidRequestDto buyBidRequestDto = BuyBidRequestDto.builder() .price(1000L) .period(7) .build(); int threadCount = 2500; List<CompletableFuture<Void>> futures = new ArrayList<>(); // WHEN for (int i = 0; i < threadCount; i++) { CompletableFuture<Void> future = CompletableFuture.runAsync( () -> doCreateBuyOfBuyer(savedBuyer, buyBidRequestDto, savedIcedAmericano)); futures.add(future); } // THEN CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); try { // Wait for all threads to finish within a specified timeout allOf.get(5, TimeUnit.MINUTES); } catch (TimeoutException e) { System.err.println("Thread Timeout : " + e.getMessage()); e.printStackTrace(); } catch (ExecutionException e) { System.err.println("Concurrency Issue : " + e.getMessage()); e.printStackTrace(); } catch (GlobalException e) { System.err.println("GlobalException Issue : " + e.getMessage()); e.printStackTrace(); } } @Transactional void doCreateBuyOfBuyer(User buyer, BuyBidRequestDto requestDto, Product product) { try { // Introduce a timeout mechanism for the method call CompletableFuture<Void> productFuture = CompletableFuture.runAsync(() -> productService.findAll()); productFuture.get(30, TimeUnit.SECONDS); // Adjust timeout as needed // Introduce a timeout mechanism for the method call CompletableFuture<Void> buyFuture = CompletableFuture.runAsync(() -> buyBidProvider.buyBidProduct(buyer, requestDto, product)); buyFuture.get(30, TimeUnit.SECONDS); // Adjust timeout as needed } catch (InterruptedException | TimeoutException e) { System.err.println("Operation timed out or interrupted: " + e.getMessage()); e.printStackTrace(); // Log or handle the timeout issue here } catch (ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof RuntimeException) { System.err.println("Concurrency issue detected: " + cause.getMessage()); cause.printStackTrace(); // Log or handle the concurrency issue here } else { // Rethrow the exception if it's not a concurrency issue throw new RuntimeException("Unexpected exception", cause); } } // productService.findAll(); // buyBidProvider.buyBidProduct(buyer, requestDto, product); } }
 
๊ทธ๋žฌ๋”๋‹ˆ ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋‚˜์™”๋‹ค.
org.springframework.dao.PessimisticLockingFailureException: could not execute statement [Lock wait timeout exceeded; try restarting transaction] [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)]; SQL [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)] 2024-02-02T17:03:36.152+09:00 INFO 8296 --- [onPool-worker-7] i.StatisticalLoggingSessionEventListener : Session Metrics { 7400 nanoseconds spent acquiring 1 JDBC connections; 0 nanoseconds spent releasing 0 JDBC connections; 625800 nanoseconds spent preparing 1 JDBC statements; 50300278900 nanoseconds spent executing 1 JDBC statements; 0 nanoseconds spent executing 0 JDBC batches; 0 nanoseconds spent performing 0 L2C puts; 0 nanoseconds spent performing 0 L2C hits; 0 nanoseconds spent performing 0 L2C misses; 0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections); 0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections) } 2024-02-02T17:03:36.152+09:00 INFO 8296 --- [onPool-worker-2] i.StatisticalLoggingSessionEventListener : Session Metrics { 10200 nanoseconds spent acquiring 1 JDBC connections; 0 nanoseconds spent releasing 0 JDBC connections; 791300 nanoseconds spent preparing 1 JDBC statements; 50299941201 nanoseconds spent executing 1 JDBC statements; 0 nanoseconds spent executing 0 JDBC batches; 0 nanoseconds spent performing 0 L2C puts; 0 nanoseconds spent performing 0 L2C hits; 0 nanoseconds spent performing 0 L2C misses; 0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections); 0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections) } 2024-02-02T17:03:36.152+09:00 INFO 8296 --- [onPool-worker-6] i.StatisticalLoggingSessionEventListener : Session Metrics { 10300 nanoseconds spent acquiring 1 JDBC connections; 0 nanoseconds spent releasing 0 JDBC connections; 1488400 nanoseconds spent preparing 1 JDBC statements; 50306876200 nanoseconds spent executing 1 JDBC statements; 0 nanoseconds spent executing 0 JDBC batches; 0 nanoseconds spent performing 0 L2C puts; 0 nanoseconds spent performing 0 L2C hits; 0 nanoseconds spent performing 0 L2C misses; 0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections); 0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections) } at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:265) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:232) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550) at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:243) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:164) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244) at jdk.proxy2/jdk.proxy2.$Proxy206.save(Unknown Source) at bc1.gream.domain.buy.provider.BuyBidProvider.buyBidProduct(BuyBidProvider.java:55) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703) at bc1.gream.domain.buy.provider.BuyBidProvider$$SpringCGLIB$$0.buyBidProduct(<generated>) at bc1.gream.deadlock.DeadlockTest.lambda$doCreateBuyOfBuyer$2(DeadlockTest.java:92) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.helpAsyncBlocker(ForkJoinPool.java:1253) at java.base/java.util.concurrent.ForkJoinPool.helpAsyncBlocker(ForkJoinPool.java:2237) at java.base/java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1933) at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2095) at bc1.gream.deadlock.DeadlockTest.doCreateBuyOfBuyer(DeadlockTest.java:93) at bc1.gream.deadlock.DeadlockTest.lambda$์Šค๋ ˆ๋“œ2500๊ฐœ_๋™์‹œ์—_๊ตฌ๋งค์ž…์ฐฐ์ƒ์„ฑ์š”์ฒญ$0(DeadlockTest.java:62) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) Caused by: org.hibernate.PessimisticLockException: could not execute statement [Lock wait timeout exceeded; try restarting transaction] [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)] at org.hibernate.dialect.MySQLDialect.lambda$buildSQLExceptionConversionDelegate$3(MySQLDialect.java:1166) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:278) at org.hibernate.id.insert.GetGeneratedKeysDelegate.performInsert(GetGeneratedKeysDelegate.java:107) at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorPostInsertSingleTable.execute(MutationExecutorPostInsertSingleTable.java:100) at org.hibernate.persister.entity.mutation.InsertCoordinator.doStaticInserts(InsertCoordinator.java:171) at org.hibernate.persister.entity.mutation.InsertCoordinator.coordinateInsert(InsertCoordinator.java:112) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2784) at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81) at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:676) at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:291) at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:272) at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:322) at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:363) at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:277) at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:140) at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:175) at org.hibernate.event.internal.DefaultPersistEventListener.persist(DefaultPersistEventListener.java:93) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:77) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:54) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:755) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:739) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:312) at jdk.proxy2/jdk.proxy2.$Proxy192.persist(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:618) at jdk.internal.reflect.GeneratedMethodAccessor57.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:288) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120) at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516) at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285) at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:70) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ... 40 more Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:124) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916) at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1061) at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1009) at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1320) at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:994) at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:275) ... 88 more Concurrency issue detected: could not execute statement [Lock wait timeout exceeded; try restarting transaction] [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)]; SQL [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)] Concurrency issue detected: could not execute statement [Lock wait timeout exceeded; try restarting transaction] [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)]; SQL [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)] org.springframework.dao.PessimisticLockingFailureException: could not execute statement [Lock wait timeout exceeded; try restarting transaction] [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)]; SQL [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)] at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:265) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:232) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550) at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:243) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:164) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) 2024-02-02T17:03:36.155+09:00 TRACE 8296 --- [onPool-worker-5] o.s.t.i.TransactionInterceptor : Getting transaction for [bc1.gream.domain.product.service.query.ProductService.findAll] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244) at jdk.proxy2/jdk.proxy2.$Proxy206.save(Unknown Source) at bc1.gream.domain.buy.provider.BuyBidProvider.buyBidProduct(BuyBidProvider.java:55) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) 2024-02-02T17:03:36.155+09:00 TRACE 8296 --- [onPool-worker-5] o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703) at bc1.gream.domain.buy.provider.BuyBidProvider$$SpringCGLIB$$0.buyBidProduct(<generated>) at bc1.gream.deadlock.DeadlockTest.lambda$doCreateBuyOfBuyer$2(DeadlockTest.java:92) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.helpAsyncBlocker(ForkJoinPool.java:1253) at java.base/java.util.concurrent.ForkJoinPool.helpAsyncBlocker(ForkJoinPool.java:2237) at java.base/java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1933) at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2095) at bc1.gream.deadlock.DeadlockTest.doCreateBuyOfBuyer(DeadlockTest.java:93) at bc1.gream.deadlock.DeadlockTest.lambda$์Šค๋ ˆ๋“œ2500๊ฐœ_๋™์‹œ์—_๊ตฌ๋งค์ž…์ฐฐ์ƒ์„ฑ์š”์ฒญ$0(DeadlockTest.java:62) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)

๐Ÿค” Reason


The error message you provided indicates a PessimisticLockingFailureException, which is thrown when a database lock wait timeout occurs. This usually happens when one transaction is waiting for a lock held by another transaction for too long.
The key part of the error message is:
Lock wait timeout exceeded; try restarting transaction
This suggests that one transaction is waiting to acquire a lock on a database resource that is currently held by another transaction for too long, resulting in a timeout.
 
์Œ,, ๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ค ์ฝ”๋“œ๋กœ ์ธํ•ด ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ Lock์„ ๊ธธ๊ฒŒ ์žก๊ณ  ์žˆ๋Š”๊ฑธ๊นŒ??
Concurrency issue detected: could not execute statement [Lock wait timeout exceeded; try restarting transaction] [insert into `tb_buy` (`coupon_id`,`created_at`,`deadline_at`,`modified_at`,`price`,`product_id`,`user_id`) values (?,?,?,?,?,?,?)];
์—๋Ÿฌ๋Š” Buy ์—”ํ‹ฐํ‹ฐ save() ์—์„œ ๋ฐœ์ƒํ–ˆ๋‹ค. ์™ค๊นŒ??
์—๋Ÿฌ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.
  1. ์—ฌ๋Ÿฌ ํŠธ๋žœ์žญ์…˜
    1. ๋™์ผํ•œ ์‚ฌ์šฉ์ž์— ๋Œ€ํ•œ ๊ตฌ๋งค ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ €์žฅํ•˜๋ ค๋Š” ์—ฌ๋Ÿฌ ํŠธ๋žœ์žญ์…˜์ด ๋™์‹œ์— ์‹คํ–‰ ์ค‘์ด๋‹ค.
  1. Lock
    1. ํ•œ ํŠธ๋žœ์žญ์…˜์ด ๊ตฌ๋งค์ž…์ฐฐ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ €์žฅํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ƒˆ๋กœ์šด ํ–‰์— ๋Œ€ํ•œ Lock์„ ํš๋“ํ•˜์—ฌ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์ด ๋™์‹œ์— ์ˆ˜์ •ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ํ•œ๋‹ค.
  1. ๊ฒฝํ•ฉ ์ค‘์ธ ํŠธ๋žœ์žญ์…˜
    1. ์—ฌ๋Ÿฌ ํŠธ๋žœ์žญ์…˜์ด ๋™์ผํ•œ ์‚ฌ์šฉ์ž์˜ ๊ตฌ๋งค ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋™์‹œ์— ์ €์žฅํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋Š” ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋™์ผํ•œ ํ–‰์— ๋Œ€ํ•œ Lock์— ๋Œ€ํ•ด์„œ ์—ฌ๋Ÿฌ ํŠธ๋žœ์žญ์…˜ ๊ฐ„ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•œ๋‹ค.
  1. Lock wait timeout
    1. ํ•œ ํŠธ๋žœ์žญ์…˜์ด ์žฅ๊ธฐ๊ฐ„ Lock์„ ์œ ์ง€ํ•˜๋ฉด ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์ด Lock ํ•ด์ œ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•œ๋‹ค.๋Œ€๊ธฐ ์ค‘์ธ ํŠธ๋žœ์žญ์…˜์ด ์ž ๊ธˆ ๋Œ€๊ธฐ ์‹œ๊ฐ„ ์ดˆ๊ณผ ์ž„๊ณ„๊ฐ’์„ ์ดˆ๊ณผํ•˜๋ฉด PessimisticLockingFailureException์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โ˜๏ธSolution & Improvement


GPT์—๊ฒŒ ๋ฌผ์–ด๋ณด๋‹ˆ ํ•ด๊ฒฐ๋ฐฉ์•ˆ์œผ๋กœ ์—ฌ๋Ÿฌ ์˜ต์…˜์„ ์ œ์‹œํ•ด์ฃผ์—ˆ๋‹ค.
  1. Optimistic Locking: Consider using optimistic locking instead of pessimistic locking. With optimistic locking, instead of blocking other transactions from accessing the locked resource, you detect conflicts when a transaction attempts to update a stale version of the data. Spring Data JPA supports optimistic locking through the @Version annotation.
  1. Retry Mechanism: Implement a retry mechanism for the affected transactions. When a PessimisticLockingFailureException occurs, you can catch the exception and retry the transaction after a short delay. You can use Spring's @Retryable annotation along with @EnableRetry to automatically retry failed transactions with configurable backoff and retry limits.
  1. Adjust Transaction Isolation Levels: Review the transaction isolation levels used in your application. Lowering the isolation level may reduce the likelihood of lock contention, but it may also introduce other consistency issues. Choose the appropriate isolation level based on your application's requirements.
  1. Optimize Transactions: Review the scope and duration of your transactions. Long-running transactions increase the likelihood of lock contention. Consider breaking down transactions into smaller units of work or using read-only transactions where applicable.
  1. Database Tuning: Analyze database performance and consider tuning database parameters related to locking, concurrency, and transaction management. Adjusting parameters such as lock timeout, concurrency control mechanisms, and transaction isolation levels can help alleviate lock contention issues.
  1. Monitor and Analyze: Monitor database locking and transaction behavior using database monitoring tools. Analyze lock wait times, transaction timeouts, and contention patterns to identify performance bottlenecks and areas for optimization.
 
 

Pessimistic Lock VS Optimistic Lock

notion image
Optimistic Locking allows a conflict to occur, but it needs to detect it at write time. This can be done using either a physical or a logical clock. However, since logical clocks are superior to physical clocks when it comes to implementing a concurrency control mechanism, we are going to use a version column to capture the read-time row snapshot information.
The version column is going to be incremented every time an UPDATE or DELETE statement is executed while also being used for matching the expected row snapshot in the WHERE clause.
notion image

๋‚™๊ด€์  ๋ฝ

  • ํŠธ๋žœ์žญ์…˜ ๋Œ€๋ถ€๋ถ„์€ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๋‚™๊ด€์ ์œผ๋กœ ๊ฐ€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฝ ๊ธฐ๋Šฅ์ด ์•„๋‹Œ JPA๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฒ„์ „ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉ
    • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ œ๊ณตํ•˜๋Š” ๋ฝ
    • ๋ฒ„์ „์„ ํ†ตํ•ด ๋ฝ์„ ์ธ์ง€
  • ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ํŠธ๋žœ์žญ์…˜์˜ ์ถฉ๋Œ์„ ์•Œ ์ˆ˜ ์—†๋‹ค.

4.4 ๋น„๊ด€์  ๋ฝ

notion image
In the diagram above, both Alice and Bob will acquire a read (shared) lock on the account table row upon reading it.
Because both Alice and Bob hold the read (shared) lock on the account record with the identifier value of 1, neither of them can change it until one releases the read lock they acquired. This is because a write operation requires a write (exclusive) lock acquisition, and read (shared) locks prevent write (exclusive) locks.
For this reason, Bobโ€™s UPDATE blocks until Alice releases the shared lock she has acquired previously.
  • ํŠธ๋žœ์žญ์…˜์˜ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์šฐ์„  ๋ฝ์„ ๊ฑธ๊ณ  ๋ณด๋Š” ๋ฐฉ๋ฒ•
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฝ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ์ฆ‰์‹œ ํŠธ๋žœ์žญ์…˜ ์ถฉ๋Œ์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

Optimistic Lock Annotations

  • PESSIMISTIC_READ allows us to obtain a shared lock and prevent the data from being updated or deleted.
  • PESSIMISTIC_WRITE allows us to obtain an exclusive lock and prevent the data from being read, updated or deleted.
  • PESSIMISTIC_FORCE_INCREMENT works like PESSIMISTIC_WRITE, and it additionally increments a version attribute of a versioned entity.
 
๊ฐœ์ธ์ ์˜๊ฒฌ
ํ ,,,save()์—์„œ ์—๋Ÿฌ๊ฐ€ ์™ธ๋ž˜ํ‚ค๋กœ ์ธํ•ด ๋ฝ ํƒ€์ž„์•„์›ƒ์ด ๋ฐœ์ƒํ–ˆ๋‹ค, ๊ทธใ…“ใ…Ž๋‹ค๋ฉด ๋น„๊ด€์  ๋ฝ & ๋™์‹œ์ ‘์† ์ œํ•œ์„ ํ†ตํ•ด ๋™์‹œ์„ฑ ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผํ—ˆ์ง€ ์•Š์„๊นŒ?
 
Share article

tony-tech