文章目录
- 共享锁(读锁也叫S锁)/排他锁(写锁也叫X锁)
- 行锁
- 表锁
- 意向锁
- 间隙锁
- 乐观锁
- 悲观锁
共享锁(读锁也叫S锁)/排他锁(写锁也叫X锁)
共享锁(S锁)
:当一个事务给一条记录上共享锁后,其他的事务也可以对该事务上共享锁,但是该锁只是可以读,如果有事务想写,那么它就会阻塞,一直等待所有的锁释放。排他锁(X锁)
:当一个事务给记录上锁后,可以进行读写,其他的事务不能够上任何锁。
行锁
- innodb既支持行锁,也支持表锁
行锁
开销大,会出现死锁,发生冲突几率小,并发高- MySQL的行锁是通过索引加载的,锁住的永远是索引,而非记录本身,即使没有索引innodb会在后台创建一个聚簇索引,行锁就会锁住聚簇索引,
但是如果一个SQL语句没有走任何索引,那么就会为它加上表锁,全表扫描。
表锁
- 针对数据库的表进行加锁。不会出现死锁,发生锁的冲突几率高,并发低。
- MySQL表锁有俩个模式:
表共享读锁和表独占写锁
表级自增锁
,当为表的某一列添加AUTO_INCREAMENT属性后,插入数据可以不指定该字段,系统会自动为它赋值。此时获取自增值是需要AUTO_INC锁锁定的- MyISANM不适合做写为主表的引擎,因为它是表锁,当锁住后,其他的线程不能做任何操作,从而大量更新会使得查询很难得到锁,最终导致永久阻塞。
意向锁
如果出现行锁的时候,想加表锁,那就只能进行全表遍历,看是否有加行锁。太浪费时间
意向锁是则不需要进行遍历数据也可以直接判断是否可以给表加锁
。意向共享锁(IS锁)
:当事务给某行记录增加了S锁(共享锁),同时给表加一个IS锁意向独占锁(IX锁)
:当事务给某条记录增加X锁时(独占锁),同时给表加一个IX锁。
- 意向锁是innodb自动加的,不用用户干预。
间隙锁
MySQL默认隔离级别是可重复读
,而可重读读只能解决脏读,不可重复读。解决不了幻读
,但是不同的一点是MySQL通过俩种机制来解决幻读:一靠MVCC方案解决,二加锁方案解决
。然而事务加锁时,记录是不存在的,是无法加行锁,则需要靠间隙锁。
- 例如给 id=8 记录加 gap 锁,锁住(4,8)区间。另一事务想插入 id=6 的记录,会先定位到 id=8 的记录,然后发现存在一个 gap 锁,则阻塞直到 第一个事务将 gap 锁释放掉,才可以在(4,8)区间插入记录
- gap lock 仅仅是为了防止插入幻影记录,并不会限制其他事务对记录继续加行锁 或者 gap 锁
乐观锁
-
每次拿
数据
都默认别人不会修改,所以不会上锁,在更新的时候会判断一下在此期间别人有没有去更新这个数据。 -
实现方式
:乐观锁一般会使用版本号机制或CAS算法实现。 -
MVCC (Multiversion Concurrency Control),即多版本并发控制技术。
-
MVCC在MySQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁
总结
:
MVCC其本质就是看做是乐观锁的机制,而排他锁等则是悲观锁的实现。
悲观锁
- 每次拿数据时都认为别人会修改,所以每次那数据时都会上锁,别人拿数据时会阻塞直到拿到锁。