为什么我的事务在MySQL中陷入僵局?

时间:2015-12-23 06:49:10

标签: java mysql sql spring hibernate

我正在使用Spring Data JPA和Hibernate来创建这样的事务:

@Autowired
private PingRepository repository;

@Transactional
public void processPing(Ping ping)
{
    Ping storedPing = repository.findById(ping.id);

    if (storedPing == null)
    {
        repository.save(ping);
    } else
    {
        if (ping.lastProcessTime > storedPing.lastProcessTime)
        {
            storedPing.setLastProcessTime(ping.lastProcessTime);
        }
    }
}

public interface PingRepository extends CrudRepository<Ping, PingKey>
{
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    Ping findById(PingKey id);
}

虽然大部分时间上面的代码都成功了,但我也看到了很多例外情况:

caused by com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:
Deadlock found when trying to get lock; try restarting transaction
com.dripstat.alerts.app.store.PingOps$$EnhancerBySpringCGLIB$$4b6adccb.processPing(<generated>)
<more stacktrace....>

这是Ping表更新的唯一地方。

上面的processPing()方法怎么可能会遇到死锁?

更新:

以下是SHOW ENGINE INNODB STATUS命令的一些相关输出:

------------------------
LATEST DETECTED DEADLOCK
------------------------
2015-12-23 05:57:47 7f23d73c6700
*** (1) TRANSACTION:
TRANSACTION 32990178, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1184, 2 row lock(s)
MySQL thread id 314344, OS thread handle 0x7f23d6480700, query id 99645000 104.197.97.45 dsprod update
insert into pings (lastProcessTime, id, type) values (1450845, '52c7e28eebb26a86fb1505b5', 'INCIDENT')
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 17 page no 4 n bits 376 index `PRIMARY` of table `alerts`.`pings` trx id 32990178 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 24; hex 353363336635646430636632336133633062623934613866; asc 53c3f5dd0cf23a3c0bb94a8f;;
 1: len 3; hex 415050; asc APP;;
 2: len 6; hex 000001f76076; asc     `v;;
 3: len 7; hex 5a000001e10b80; asc Z      ;;
 4: len 4; hex d67a36f8; asc  z6 ;;

*** (2) TRANSACTION:
TRANSACTION 32990184, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1184, 2 row lock(s)
MySQL thread id 314341, OS thread handle 0x7f23d73c6700, query id 99645014 104.197.97.45 dsprod update
insert into pings (lastProcessTime, id, type) values (1450848, '52c7e28eebb26a86fb1505b5', 'INCIDENT')
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 17 page no 4 n bits 376 index `PRIMARY` of table `alerts`.`pings` trx id 32990184 lock_mode X locks gap before rec
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 24; hex 353363336635646430636632336133633062623934613866; asc 53c3f5dd0cf23a3c0bb94a8f;;
 1: len 3; hex 415050; asc APP;;
 2: len 6; hex 000001f76076; asc     `v;;
 3: len 7; hex 5a000001e10b80; asc Z      ;;
 4: len 4; hex d67a36f8; asc  z6 ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 17 page no 4 n bits 376 index `PRIMARY` of table `alerts`.`pings` trx id 32990184 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 24; hex 353363336635646430636632336133633062623934613866; asc 53c3f5dd0cf23a3c0bb94a8f;;
 1: len 3; hex 415050; asc APP;;
 2: len 6; hex 000001f76076; asc     `v;;
 3: len 7; hex 5a000001e10b80; asc Z      ;;
 4: len 4; hex d67a36f8; asc  z6 ;;

*** WE ROLL BACK TRANSACTION (2)

1 个答案:

答案 0 :(得分:0)

代码在语义上是正确的 这是mysql中的一个错误。 https://bugs.mysql.com/bug.php?id=48911