锁机制的定义:计算机 协调多个过程或线程并发拜访某一资源的机制。
加锁尽管能防止事务的抵触,然而加锁是耗费资源的,锁的各种操作,包含取得锁、检测锁是否已解除、开释锁等,都会减少零碎的开销。
MySQL 的行锁和表锁
表锁
有读锁(共享锁)和写锁(独占锁),存储默认引擎为 MyISAM,当一个线程取得对一个表的写锁后,只有持有锁线程能够对表进行更新操作。其余线程的读、写操作都会期待,直到锁被开释为止。
特点:
- 对整张表加锁
- 开销小
- 加锁快
- 无死锁
- 锁粒度大,产生锁抵触概率大,并发性低
MyISAM 的读写锁调度是 写优先,这也是MyISAM 不适宜做写为主表的引擎,因为写锁当前,其它线程不能做任何操作,大量的更新使查问很难失去锁,从而造成永远阻塞。
行锁
默认引擎:InnoDB,留神:InnoDB 反对事务,MyISAM 不反对事务。
读锁、写锁、动向共享锁、动向排他锁
动向共享锁(IS)
一个事务给一个数据行加共享锁时,必须先取得表的 IS 锁
动向排它锁(IX)
一个事务给一个数据行加排他锁时,必须先取得该表的 IX 锁
特点:
- 对一行数据加锁
- 开销大
- 加锁慢
- 会呈现死锁
- 锁粒度小,产生锁抵触概率最低,并发性高
事务并发的问题:
- 更新失落
解决:让事务变成串行操作,而不是并发的操作,即对每个事务开始 — 对读取记录加排他锁 - 脏读
解决:隔离级别为 Read uncommitted - 不可重读
解决:应用 Next-Key Lock 算法来防止 - 幻读
解决:间隙锁(Gap Lock)
页锁
开销、加锁工夫和锁粒度介于表锁和行锁之间,会呈现死锁,并发解决能力个别(此锁不做多介绍)
隐式上锁
select // 表锁上读锁,行锁不上锁
insert、update、delete // 上写锁
显式上锁
lock table tableName read;// 读锁
lock table tableName write;// 写锁
select * from tableName lock in share mode;// 读锁
select * from tableName for update;// 写锁
死锁产生条件
- 互斥条件:一个资源每次只能被一个过程应用
- 申请与放弃条件:一个过程因申请资源而阻塞时,对已取得的资源放弃不放
- 不剥夺条件:过程已取得的资源,在没有应用完之前,不能强行剥夺
- 循环期待条件:多个过程之间造成的一种相互循环期待的资源的关系
如何防止死锁
(1)死锁预防:通过确保死锁的一个必要条件不会满足,保障不会产生死锁。
(2)死锁检测:设置检测算法。
(3)死锁防止:银行家算法分配资源。如果一个过程的申请会导致死锁,则不启动该过程。
(4)死锁解除:资源剥夺法、过程撤销法。