排它锁

其他事务不能读取和修改

MySQL有三种级别:页级、表级、行级。

表级锁:开销小,加锁快;锁定粒度大,发生锁冲突的概率最高,并发度最低。

​ 表级锁性能问题较大,如果出现locked状态,一般来说就是表锁的锅

行级锁:开销大,加锁慢;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

页面锁:开销和加锁时间界于表锁和行锁之间;锁定粒度界于表锁和行锁之间,并发度一般

共享锁

其他事务可以读取,不能修改

MVCC

Multi-Version Concurrent Control 多版本并发控制

原理

保存数据快照,操作副本。也就是在不同事物里面,因为副本的原因同一时间看见的同一数据可能是不一样的

不同副本之间用版本号区别,数据库会内置系统版本号,每经过一次事物就将版本号+1

工作的隔离级别

mysql实现:

REPEATABLE READ

READ COMMITTED

在这两个隔离级别才会使用mvcc

mysql innodb

乐观锁

悲观锁

  • 获取结果集之后,对结果集加行锁
  • 对于非主键、非索引字段查询加表锁

sql语句

实现:通过for update(在没有指定主键的情况下,innodb的行锁将变成表锁)

解决:幻读

引发:死锁(两个(或以上)的Session加锁的顺序不一致)

Jpa实现

  1. 线程加上事务: @Transactional(isolation = Isolation.READ_COMMITTED)

注意:事务注解添加的时候嵌套容易引发死锁

  1. 自己写的查询语句注解:@Lock(value = LockModeType.PESSIMISTIC_WRITE)

发生死锁原因

  1. 业务逻辑问题,使得上锁顺序颠倒。锁表和锁行都可能发生
  2. 共享锁上升到排它锁
  3. 在锁有索引的情况下,如果在索引里面有多个添加索引的字段,字段顺序相反