结论

普通查询 查询(加共享锁) 查询(加排它锁) 插入/更新
间隙锁 不阻塞 不阻塞 不阻塞 阻塞
行锁 不阻塞 阻塞 阻塞 阻塞

MySQL版本:5.7.26

实验过程

  1. 写一个程序模拟实际代码:
@SneakyThrows
@Transactional
public String testPessimisticWrite(String username) {
    log.info("start query");  
    // select * where testtable0_.username=:username for update;
    TestTable testTable1 = testTableDao.findPessimisticWriteByUsername(username).orElse(null);
    log.info("finished query" + testTable1);

    // (1)
    TimeUnit.SECONDS.sleep(6000);
    return "ok";
}
  1. TestTable表结构及数据:

  • 启用一个线程调用1.中方法查询username:233
  • 启用一个线程调用1.中方法查询username:2334
    以上两个线程都会在(1)处阻塞。

此时用数据库管理工具去查询一下这两条数据:

  1. 使用普通查询语句:select * from test_table where username = <username>

    • 查询233不会阻塞
    • 查询2334不会阻塞
  2. 使用lock in share mode查询语句:select * from test_table where username = <username> lock in share mode

    • 查询233会阻塞
    • 查询2334不会阻塞
  3. 使用for update查询语句:select * from test_table where username = <username> for update

    • 查询233会阻塞
    • 查询2334不会阻塞
  4. 插入2334:会阻塞