0

我有一个登录 API,它会在每个用户登录时被调用,作为此登录 API 的一部分,我必须更新用户的最后登录时间。因此,每当用户登录时,我们都需要更新用户的上次登录时间,并且这是在服务内部处理的,服务调用存储库(JPA 存储库)。请参阅下面的代码以了解其设计方式。

@Transactional
@Modifying
@Query("update UserAuth userAuth set " +
            " userAuth.pwdFailureCount=0, " +
            " userAuth.modifiedTS = current_timestamp , " +
            " userAuth.lastLoginTS = current_timestamp " +
            " where userAuth.userid = :userid and userAuth.appid=:appid")
void updateLastLoginDetails(@Param("userid") String userid,@Param("appid") String appid);

尽管使它具有事务性,但仍以某种方式发生了僵局。根据我的分析,这种死锁是由自动化用户同时调用登录 API 引起的,从而导致死锁情况。请查看从数据库服务器收集的死锁日志。数据库是 MySQL。


------------------------
LATEST DETECTED DEADLOCK
------------------------
2021-06-23 14:18:29 2b17a587d700
*** (1) TRANSACTION:
TRANSACTION 1084393596, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 376, 2 row lock(s)
MySQL thread id 73679663, OS thread handle 0x2b17f2481700, query id 1997246337 10.3.61.147 authmanager updating
update UserAuth set PWD_FAILURE_COUNT=0, MODIFIED_TS=current_timestamp, LAST_LOGIN_TS=current_timestamp, where userid=‘kambalavijay19 and appid=‘app1’
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 223 page no 140535 n bits 30 index `PRIMARY` of table `auth_db`.`userauth` trx id 1084393596 lock_mode X locks rec but not gap waiting
Record lock, heap no 30 PHYSICAL RECORD: n_fields 25; compact format; info bits 0
 0: len=8; bufptr=0x2b0f8840b5cc; hex= 80000000002fd7f4; asc      /  ;;
 1: len=6; bufptr=0x2b0f8840b5d4; hex= 000040a2887b; asc   @  {;;
 2: len=7; bufptr=0x2b0f8840b5da; hex= 28000019222295; asc (   "" ;;
 3: len=30; bufptr=0x2b0f8840b5e1; hex= 64643635373264312d356266332d343531622d626236652d323932346638; asc dd6572d1-5bf3-451b-bb6e-2924f8; (total 36 bytes);
 4: len=10; bufptr=0x2b0f8840b605; hex= 6f7074756d676f766964; asc optumgovid;;
 5: len=14; bufptr=0x2b0f8840b60f; hex= 6175746f6d6174696f6e666e6c6e; asc automationfnln;;
 6: len=30; bufptr=0x2b0f8840b61d; hex= 316c626f316d44684f2f7359684f373463486c4c7a63753239586e41694c; asc 1lbo1mDhO/sYhO74cHlLzcu29XnAiL; (total 44 bytes);
 7: len=30; bufptr=0x2b0f8840b649; hex= 4e644b7a4a6d67664b4a4341767755746761755677753844506544743363; asc NdKzJmgfKJCAvwUtgauVwu8DPeDt3c; (total 44 bytes);
 8: len=30; bufptr=0x2b0f8840b675; hex= 4159414465484777714938706c6f344d4752735054354639414255416751; asc AYADeHGwqI8plo4MGRsPT5F9ABUAgQ; (total 1216 bytes);
 9: len=10; bufptr=0x2b0f8840bb35; hex= 486d6163534841323536; asc HmacSHA256;;
 10: len=6; bufptr=0x2b0f8840bb3f; hex= 414354495645; asc ACTIVE;;
 11: SQL NULL;
 12: len=11; bufptr=0x2b0f8840bb45; hex= 7077642c7371612c73736f; asc pwd,sqa,sso;;
 13: len=6; bufptr=0x2b0f8840bb50; hex= 414354495645; asc ACTIVE;;
 14: len=1; bufptr=0x2b0f8840bb56; hex= 80; asc  ;;
 15: SQL NULL;
 16: len=4; bufptr=0x2b0f8840bb57; hex= 60b10c4f; asc `  O;;
 17: len=4; bufptr=0x2b0f8840bb5b; hex= 60d342b5; asc ` B ;;
 18: len=4; bufptr=0x2b0f8840bb5f; hex= 5c35e073; asc \5 s;;
 19: len=4; bufptr=0x2b0f8840bb63; hex= 60d342b5; asc ` B ;;
 20: len=3; bufptr=0x2b0f8840bb67; hex= 4b4d53; asc KMS;;
 21: SQL NULL;
 22: len=1; bufptr=0x2b0f8840bb6a; hex= 00; asc  ;;
 23: SQL NULL;
 24: len=3; bufptr=0x2b0f8840bb6b; hex= 616263; asc abc;;

*** (2) TRANSACTION:
TRANSACTION 1084393595, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 376, 2 row lock(s), undo log entries 1
MySQL thread id 73679662, OS thread handle 0x2b15a6281700, query id 1997246338 10.3.52.220 authmanager updating
update UserAuth set PWD_FAILURE_COUNT=0, MODIFIED_TS=current_timestamp, LAST_LOGIN_TS=current_timestamp where userid=‘kambala’vijay19 and appid=‘appid’
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 223 page no 140535 n bits 30 index `PRIMARY` of table `authdb`.`userauth` trx id 1084393595 lock_mode X locks rec but not gap
Record lock, heap no 30 PHYSICAL RECORD: n_fields 25; compact format; info bits 0
 0: len=8; bufptr=0x2b0f8840b5cc; hex= 80000000002fd7f4; asc      /  ;;
 1: len=6; bufptr=0x2b0f8840b5d4; hex= 000040a2887b; asc   @  {;;
 2: len=7; bufptr=0x2b0f8840b5da; hex= 28000019222295; asc (   "" ;;
 3: len=30; bufptr=0x2b0f8840b5e1; hex= 64643635373264312d356266332d343531622d626236652d323932346638; asc dd6572d1-5bf3-451b-bb6e-2924f8; (total 36 bytes);
 4: len=10; bufptr=0x2b0f8840b605; hex= 6f7074756d676f766964; asc app1;;
 5: len=14; bufptr=0x2b0f8840b60f; hex= 6175746f6d6174696f6e666e6c6e; asc automationfnln;;
 6: len=30; bufptr=0x2b0f8840b61d; hex= 316c626f316d44684f2f7359684f373463486c4c7a63753239586e41694c; asc 1lbo1mDhO/sYhO74cHlLzcu29XnAiL; (total 44 bytes);
 7: len=30; bufptr=0x2b0f8840b649; hex= 4e644b7a4a6d67664b4a4341767755746761755677753844506544743363; asc NdKzJmgfKJCAvwUtgauVwu8DPeDt3c; (total 44 bytes);
 8: len=30; bufptr=0x2b0f8840b675; hex= 4159414465484777714938706c6f344d4752735054354639414255416751; asc AYADeHGwqI8plo4MGRsPT5F9ABUAgQ; (total 1216 bytes);
 9: len=10; bufptr=0x2b0f8840bb35; hex= 486d6163534841323536; asc HmacSHA256;;
 10: len=6; bufptr=0x2b0f8840bb3f; hex= 414354495645; asc ACTIVE;;
 11: SQL NULL;
 12: len=11; bufptr=0x2b0f8840bb45; hex= 7077642c7371612c73736f; asc pwd,sqa,sso;;
 13: len=6; bufptr=0x2b0f8840bb50; hex= 414354495645; asc ACTIVE;;
 14: len=1; bufptr=0x2b0f8840bb56; hex= 80; asc  ;;
 15: SQL NULL;
 16: len=4; bufptr=0x2b0f8840bb57; hex= 60b10c4f; asc `  O;;
 17: len=4; bufptr=0x2b0f8840bb5b; hex= 60d342b5; asc ` B ;;
 18: len=4; bufptr=0x2b0f8840bb5f; hex= 5c35e073; asc \5 s;;
 19: len=4; bufptr=0x2b0f8840bb63; hex= 60d342b5; asc ` B ;;
 20: len=3; bufptr=0x2b0f8840bb67; hex= 4b4d53; asc KMS;;
 21: SQL NULL;
 22: len=1; bufptr=0x2b0f8840bb6a; hex= 00; asc  ;;
 23: SQL NULL;
 24: len=3; bufptr=0x2b0f8840bb6b; hex= 616263; asc abc;;

[bitmap0 of 16 bytes in hex: 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 ]
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 223 page no 388107 n bits 198 index `UNIQUE_USERID` of table `authdb`.`userauth` trx id 1084393595 lock_mode X locks rec but not gap waiting
Record lock, heap no 198 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len=30; bufptr=0x2b146e8b68e8; hex= 64643635373264312d356266332d343531622d626236652d323932346638; asc dd6572d1-5bf3-451b-bb6e-2924f8; (total 36 bytes);
 1: len=10; bufptr=0x2b146e8b690c; hex= 6f7074756d676f766964; asc app1;;
 2: len=8; bufptr=0x2b146e8b6916; hex= 80000000002fd7f4; asc      /  ;;

*** WE ROLL BACK TRANSACTION (1)

由于锁定不可用,在应用程序日志中请求失败。请参阅下面的日志。应用程序正在 spring-boot 中编写。

org.springframework.dao.CannotAcquireLockException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.LockAcquisitionException: could not execute statement

我对正确解决这个问题的方法一无所知。有人可以解决这个问题并找到解决此问题的方法吗?我仍然希望我的自动化用户能够访问 api,但不应该出现这种故障(500)。

4

0 回答 0