mysql:锁分类,表锁(s锁,x锁,意向锁,自增锁,元数据锁)行锁( 记录锁,间隙锁,临键锁,插入意向锁)乐观锁,悲观锁,显示锁,隐式锁
1从数据操作的类型划分:读锁、写锁
- 读锁
读锁 :也称为 共享锁 、英文用 S 表示。针对同一份数据,多个事务的读操作可以同时进行而不会互相影响,相互不阻塞的。 - 写锁
写锁 :也称为 排他锁 、英文用 X 表示。当前写操作没有完成前,它会阻断其他写锁和读锁。这样就能确保在给定的时间里,只有一个事务能执行写入,并防止其他用户读取正在写入的同一资源。
2从数据操作的粒度划分:表级锁、页级锁、行锁
2.1表级锁
- 表级别的S锁、X锁
LOCK TABLES t READ :InnoDB存储引擎会对表 t 加表级别的 S锁 。
LOCK TABLES t WRITE :InnoDB存储引擎会对表 t 加表级别的 X锁
- 意向锁 (intention lock)
-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。
SELECT column FROM table ... LOCK IN SHARE MODE;
-- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。
SELECT column FROM table ... FOR UPDATE;
- 自增锁(AUTO-INC锁)
保证正常新增数据 - 元数据锁(mdl)
保证在修改表结构时不能对数据进行修改。
2.2行级锁
- 记录锁
- 间隙锁
- 临键锁
- 意向插入锁
2.3页锁
3从对待锁的态度划分:乐观锁、悲观锁
悲观锁
悲观锁是一种思想,顾名思义,就是很悲观,对数据被其他事务的修改持保守态度,会通过数据库自身的锁机制来实现,从而保证数据操作的排它性。
悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 阻塞 直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁,当其他线程想要访问数据时,都需要阻塞挂起。Java中 synchronized 和 ReentrantLock 等独占锁就是悲观锁思想的实现。
乐观锁
乐观锁认为对同一数据的并发操作不会总发生,属于小概率事件,不用每次都对数据上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,也就是不采用数据库自身的锁机制,而是通过程序来实现。在程序上,我们可以采用 版本号机制 或者 CAS机制 实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量。在Java中 java.util.concurrent.atomic 包下的原子变量类就是使用了乐观锁begin;select * from student where id <=8 and id > 3 for update;的一种实现方式:CAS实现的。
通过时间戳,或者版本号来实现,在程序上的控制
4显示锁,隐式锁
显示锁就是我们手动加的可见的
隐式锁,对聚簇索引上有trx_id字段,记录当前记录是否在其他事务中活跃