MySQL高级第四章——MySQL的锁机制

一、概述

  1.定义

    锁是计算机协调多个进程或线程并发访问某一资源的限制。

  2.分类

   操作类型来分:

    读锁(共享锁)和写锁(排它锁)

   数据粒度来分:

    表锁和行锁 

二、三锁 

  1.表锁——偏读

  特点:

    偏向 MyISAM 引擎,开销小,加锁快,无死锁,粒度大,并发低。

  常用命令:

     MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。给MyISAM表显示加锁,一般是为了一定程度模拟事务操作,实现对某一时间点多个表的一致性读取。

    查看表被锁的情况:SHOW OPEN TABLES;

    MySQL高级第四章——MySQL的锁机制

    //0即表示未被锁住

    给表加锁:LOCK TABLE tb_name read(write)  可加读写锁(即共享锁和排它锁)

    MySQL高级第四章——MySQL的锁机制

    MySQL高级第四章——MySQL的锁机制

    给表解锁:UNLOCK TABLES;

   分析锁的情况:SHOW STATUS LIKE ‘table%’;

    MySQL高级第四章——MySQL的锁机制

    //分别表示产生表锁次数,以及等待锁次数

  读锁

   我们使用上述加锁命令显式地给某张表加读锁 :LOCK TABLE t_mylock read;这时候模拟开两个终端(s1,s2)进行模拟。(假设是是在s1中加锁)

  可以发现,s1加的读锁,自己只能读这张表,不能写这张表,也不能读其他表(必须等待释放栈);

       而s2由于s1开的为共享锁,可以读锁的表,也可以读其它表,但不能直接写锁住的表(必须等待s1释放锁),只能处于阻塞状态。

  写锁

   与加读锁类似,通过s1给t_mylock表加上写锁:LOCK TABLE t_mylock write;由于写锁是排它锁,

  可以发现:s1可以读也可以写自己锁住的表(排它锁,可以为所欲为),但是自己不能读其它表(没释放,还有笔账没请呢);

       s2查其它表没问题,查锁住的表同样会阻塞(被加排它锁,被锁住了)

  关于表锁详细,可以参见http://www.cnblogs.com/chenqionghe/p/4845693.html

  2.行锁——偏写

  特点:

    偏向 InnoDB 引擎,开销大,加锁慢,有死锁,粒度小,并发高。

  由此知道InnoDB 与 MyISAM的最大不同——1是支持事务,2是采用行锁。

    事务的复习不在这里展开。

  加锁分析:

    测试环境下,关闭自动提交(SET AUTOCOMMIT=0);若s1与s2同时操作同一行记录(例如同时update),则后一个会被阻塞。

  索引失效导致行锁变表锁:

    之前索引章节提到的,VARCHAR类型必须必须加引号 '',例如a INT,b VARCHAR两列,b列加了索引,当执行:UPDATE t_lock SET b=1008 WHERE a=1;时,将会产生严重后果:行锁变表锁,此时在未提交的过程中(设置不自动提交)其它列的操作将会被阻塞!无法修改。

  间隙锁危害:

    间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间。

              针对的是范围的操作,例如操作 a>1 and a<6;会锁定2345,即使2并不存在

    关于间隙锁的更多介绍,请参见:http://www.jianshu.com/p/bf862c37c4c9

  手动锁住某一行:

    SET AUTOCOMMIT=0;

    BEGIN;

    SELECT * FROM emp WHERE id = 1 FOR UPDATE;——锁定一行

    (COMMIT)

  查看行锁情况:

    SHOW STATUS LIKE ‘innodb_row_lock%’;

  行锁的建议:

    MySQL高级第四章——MySQL的锁机制

上一篇:第四章 数据库和SQL 4-3 数据的更新(UPDATE语句的使用方法)


下一篇:数据加密之RijndaelManaged加密