zoukankan      html  css  js  c++  java
  • 理解 mysql行锁和表锁

     

    在调用存储过程中,就会涉及到表锁,行锁这一概念:所谓区别:有索引的时候就是行锁,没有索引的时候就是表索。

    innodb 的行锁是在有索引的情况下,没有索引的表是锁定全表的.

    表锁演示(无索引)

    Session1:

    mysql> set autocommit=0;

    mysql> select * from innodb_test;
    +------+-------------+
    | id   | name        |
    +------+-------------+
    |    1 | woshiceshi  | 
    |    2 | woshiceshi2 | 
    |    3 | woshiceshi3 | 
    +------+-------------+

    mysql> select * from innodb_test where id = 2 for update;
    +------+------------+
    | id   | name       |
    +------+------------+
    |    2 | woshiceshi2 | 
    +------+------------+

    Session2:

    mysql> update innodb_test set name='sjis' where id = 1 ;
    处于等待状态....

    再回到session1 commit以后,session2就出来结果了(锁定了8秒,过了8秒左右才去session1提交)。

    mysql> update innodb_test set name='sjis' where id = 1 ;
    Query OK, 1 row affected (8.11 sec)
    Rows matched: 1  Changed: 1  Warnings: 0

    实验结果是:我在session1的for update 操作看似只锁定ID为2的行其实锁定了全表,以至于后面session2的对ID为1的行update 需要等待Session1锁的释放。

    行锁演示(索引为ID)

    Session1:
    mysql> alter table innodb_test add index idx_id(id);
    Query OK, 4 rows affected (0.01 sec)
    Records: 4  Duplicates: 0  Warnings: 0

    mysql> select * from innodb_test where id = 2 for update;
    +------+------------+
    | id   | name       |
    +------+------------+
    |    2 | woshiceshi2 | 
    +------+------------+

    Session2:

    mysql> update innodb_test set name='wohaishiceshi' where id = 1 ;
    Query OK, 1 row affected (0.02 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    mysql> select * from innodb_test where id = 1;           
    +------+---------------+
    | id   | name          |
    +------+---------------+
    |    1 | wohaishiceshi | 
    +------+---------------+
    1 row in set (0.00 sec)

    实验结果:这次的锁定是锁定的行,所以没有被锁定的行(ID不为2的行)可以进行update..

     

    【转载】http://keshion.iteye.com/blog/1409563

     

     

    myisam存储引擎默认是表级锁
    innodb存储引擎默认是行级锁
    DBD存储引擎默认是页面锁
     

    表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。
    行级锁:开锁大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

    页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
     
    从上述特点可见,很难笼统的说哪种锁更好,只能就具体应用的特点来说哪种锁更合适!仅从锁的角度来说:表级锁更于以查询为主,只有少量按索引条件更新数据的应用,如WEB应用;而行级锁则更适合于有大理按索引发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理系统。
     

    mysql锁和死锁
    MyISAM和MEMORY存储引擎采用的是表级锁table-level locking
    BDB存储引擎采用的是页面锁page-level locking,但也支持表级锁
    InnoDB存储引擎既支持行级锁row-level locking,也支持表级锁,但默认情况下是采用行级锁
    表级锁 开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低
    行级锁 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高
    页面锁 开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
    仅从锁的角度来说:
    表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用
    行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理系统

    死锁
    所谓死锁<DeadLock>: 是指两个或两个以上的进程在执行过程中,
    因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.
    此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等竺的进程称为死锁进程.
    表级锁不会产生死锁.所以解决死锁主要还是真对于最常用的InnoDB.
    在遇到问题时
    先执行show processlist找到死锁线程号.然后Kill processNo
    当然主要解决还是需要去看一下具体的操作.可能产生死锁
    Show innodb status检查引擎状态 ,可以看到哪些语句产生死锁
    然后就是解决了.
    怎么解决还是要看具体什么问题.
    MyISAM使用的是 flock 类的函数,直接就是对整个文件进行锁定(叫做文件锁定),InnoDB使用的是 fcntl 类的函数,可以对文件中局部数据进行锁定(叫做行锁定),所以区别就是在这里。
    另外MyISAM的数据表是按照单个文件存储的,可以针对单个表文件进行锁定,但是InnoDB是一整个文件,把索引、数据、结构全部保存在 ibdata 文件里,所以必须用行锁定。

  • 相关阅读:
    NET6 如何使用Windows Service
    Delphi 设置窗体无标题栏和边框
    java MD5 加密 及对应的 oracle数据库中的MD5加密实现
    oracle 查看锁表进程和解锁
    创建dblink 及 同义词
    demjson python key没有引号的字符串如何转json
    Typescript Objects对象
    typescrip 数组、Map、对象方法
    mysql 日期 时间函数
    Typesrcipt日期时间
  • 原文地址:https://www.cnblogs.com/jamesbd/p/3582381.html
Copyright © 2011-2022 走看看