乐趣区

关于mysql:每日一篇731MySQL的锁机制

锁机制的定义:计算机 协调多个过程或线程并发拜访某一资源的机制

加锁尽管能防止事务的抵触,然而加锁是耗费资源的,锁的各种操作,包含取得锁、检测锁是否已解除、开释锁等,都会减少零碎的开销。

MySQL 的行锁和表锁

表锁

有读锁(共享锁)和写锁(独占锁),存储默认引擎为 MyISAM,当一个线程取得对一个表的写锁后,只有持有锁线程能够对表进行更新操作。其余线程的读、写操作都会期待,直到锁被开释为止。

特点:

  1. 对整张表加锁
  2. 开销小
  3. 加锁快
  4. 无死锁
  5. 锁粒度大,产生锁抵触概率大,并发性低

MyISAM 的读写锁调度是 写优先,这也是MyISAM 不适宜做写为主表的引擎,因为写锁当前,其它线程不能做任何操作,大量的更新使查问很难失去锁,从而造成永远阻塞。

行锁

默认引擎:InnoDB,留神:InnoDB 反对事务,MyISAM 不反对事务。

读锁、写锁、动向共享锁、动向排他锁

动向共享锁(IS)
一个事务给一个数据行加共享锁时,必须先取得表的 IS 锁

动向排它锁(IX)
一个事务给一个数据行加排他锁时,必须先取得该表的 IX 锁

特点:

  1. 对一行数据加锁
  2. 开销大
  3. 加锁慢
  4. 会呈现死锁
  5. 锁粒度小,产生锁抵触概率最低,并发性高

事务并发的问题:

  1. 更新失落
    解决:让事务变成串行操作,而不是并发的操作,即对每个事务开始 — 对读取记录加排他锁
  2. 脏读
    解决:隔离级别为 Read uncommitted
  3. 不可重读
    解决:应用 Next-Key Lock 算法来防止
  4. 幻读
    解决:间隙锁(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. 循环期待条件:多个过程之间造成的一种相互循环期待的资源的关系

如何防止死锁

(1)死锁预防:通过确保死锁的一个必要条件不会满足,保障不会产生死锁。

(2)死锁检测:设置检测算法。

(3)死锁防止:银行家算法分配资源。如果一个过程的申请会导致死锁,则不启动该过程。

(4)死锁解除:资源剥夺法、过程撤销法。

退出移动版