这是我的代码:
@Getter
@Setter
@Entity
@ToString
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
public interface UserRepository extends JpaRepository<User, Long> {
}
@Service("service1")
public class UserService1 implements Runnable {
@Autowired
private UserRepository userRepository;
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public void run() {
System.out.println("*** Start Transaction 1 ***");
User user = userRepository.findOne(1L);
user.setName("user " + Math.random());
System.out.println("Sleeping ...");
try {Thread.sleep(10000);} catch (InterruptedException e) {}
System.out.println("Updating user in Transaction 1... ");
userRepository.save(user);
System.out.println("*** Completed 1 ***");
}
}
@Service("service2")
public class UserService2 implements Runnable {
@Autowired
private UserRepository userRepository;
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public void run() {
System.out.println("*** Start Transaction 2 ***");
User user = userRepository.getOne(1L);
user.setName("User_service2");
userRepository.save(user);
System.out.println("*** Completed 2 ***");
}
}
@SpringBootApplication
@EnableTransactionManagement
public class Main {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(Main.class, args);
Executor e = Executors.newFixedThreadPool(2);
e.execute((Runnable) context.getBean("service1"));
Thread.sleep(2000);
e.execute((Runnable) context.getBean("service2"));
}
}
我有两个具有相同隔离级别的服务,都进行实体更新。完全开始后第二次开始(睡眠2秒)。第一个是“慢”的。
由于isolation = SERIALIZABLE
我希望这会为整个用户表创建一个锁,而执行它的任何服务都可以工作:
在我的情况下,service2
应该等到service1
完成它的工作,但这不会发生。
有人可以澄清为什么它不起作用?也许我在描述中遗漏了一些东西 感谢。
更新1:
添加了系统输出。
*** Start Transaction 1 ***
Hibernate: select user0_.id as id1_0_0_, user0_.name as name2_0_0_ from user user0_ where user0_.id=?
Sleeping ...
*** Start Transaction 2 ***
Hibernate: select user0_.id as id1_0_0_, user0_.name as name2_0_0_ from user user0_ where user0_.id=?
*** Completed 2 ***
Hibernate: update user set name=? where id=?
Updating user in Transaction 1...
*** Completed 1 ***
Hibernate: update user set name=? where id=?
2016-07-16 11:47:29.267 WARN 15656 --- [pool-2-thread-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1213, SQLState: 40001
2016-07-16 11:47:29.267 ERROR 15656 --- [pool-2-thread-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Deadlock found when trying to get lock; try restarting transaction
更新2:
DB:MySQL 5.6.25