举例解释一下MySQL的表锁和行锁

来源:这里教程网 时间:2026-03-01 16:23:37 作者:
一、锁的概述
 
在计算机中,锁是协调多个进程或线程并发访问某一资源的一种机制。
在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。
如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。
从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。
二、锁的分类
2.1 按数据操作的类型分类:
  • 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。

  • 写锁(排它锁):当前操作没有完成之前,它会阻断其他的写操作或读操作。

    2.2 按数据操作的粒度分:
  • 表锁:操作时,会锁定整个表。开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低。

  • 行锁:操作时,会锁定当前操作的表的某些行。开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高。

  • 页锁:操作时,会锁定当前操作的表的某些页。开销和加锁速度介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般。

    很难笼统地说哪种锁更好,只能就具体应用的特点来说哪种锁更合适!
    仅从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web 应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并查询的应用,如一些在线事务处理(OLTP)系统。
    三、MySQL的锁

    相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。InnoDB存储引擎支持行锁和表锁,MEMORY和MyISAM等存储引擎只支持表锁。
    3.1 MyISAM的表锁
    MyISAM存储引擎在执行查询语句(SELECT),会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等),会自动给涉及的表加写锁,这个过程并不需要用户干预。
    为了方便演示,我们利用系统提供的显式加锁指令:
  • 读锁:lock table table_name read;

  • 写锁:lock table table_name write;

  • 解锁:unlock tables;

     
    建立一个MyISAM存储引擎的表,并插入一些数据:
    
    
    create 
    
    table tb_myisam(
    
    
    id 
    
    INT AUTO_INCREMENT,
    
    
    name 
    
    VARCHAR(
    
    30),
    age 
    
    INT,
    PRIMARY 
    
    KEY(
    
    id)) 
    
    engine=myisam;
     
    
    
    insert 
    
    into tb_myisam(
    
    name,age) 
    
    value(
    
    'zhang3',
    
    20);
    
    
    insert 
    
    into tb_myisam(
    
    name,age) 
    
    value(
    
    'li4',
    
    21);
    
    
    insert 
    
    into tb_myisam(
    
    name,age) 
    
    value(
    
    'wang5',
    
    22);

    3.1.1 在两个会话终端来演示MyISAM的读锁:

     

    3.1.2 演示MyISAM的写锁:

    3.2 InnoDB的表锁和行锁

    InnoDB存储引擎在执行更新操作(UPDATE、DELETE、INSERT等),会自动给涉及的表或行加写锁。
     
    InnoDB存储引擎对于普通SELECT语句,不会加任何锁。如果读的数据正在执行UPDATE或DELETE操作,这时读操作不会等待写锁的释放,而是直接读取该数据的快照,具体读取那份快照数据,和系统的隔离级别有关。
     
    对于SELECT语句,系统提供了显式加锁指令:
  • 读锁:select * from table_name where ... lock in share mode;

  • 写锁:select * from table_name where ... for update;

    建立一个MyISAM存储引擎的表,并插入一些数据:
    create table tb_innodb (id INT AUTO_INCREMENT,name VARCHAR(30),age INT,PRIMARY KEY(id)) engine=innodb; insert into tb_innodb(name,age) value('zhang3',20);insert into tb_innodb(name,age) value('li4',21);insert into tb_innodb(name,age) value('wang5',22);
    为了方便演示,我们需要关闭系统的自动提交
     
    3.2.1 演示InnoDB表的读锁:

     
    3.2.2 演示InnoDB表的写锁:

    3.2.3 演示InnoDB行的读锁:

    3.2.4 演示InnoDB行的写锁:

    END

  • 相关推荐