锁模块

MyISAM与InnoDB关于锁的区别

  • MyISAM用的是表级锁,不支持行级锁,不支持事务

    • 例如对某表前两百万行进行查询时,MyISAM会自动给表上表锁,

      此时想修改第两百零一万行的数据就需要等待前面的查询操作执行结束。

    • 故在做查询时MyISAM会给表加上表级读锁,在修改写入等操作时会加上表级写锁。

    • 当读锁未被释放,另一个session想加上写锁就会被阻塞,直到所有的读锁都被释放。

    • 先上读锁,后上读锁不会被阻塞,后上写锁会被阻塞

    • 先上写锁,后上读写锁都会被阻塞

  • InnoDB默认用行级锁,也支持表级锁,支持事务

    • 用的二段锁:

      • 即加锁和解锁分为两个步骤,先对同一个事物中的一批操作进行加锁,commit提交后再对加上的锁统一解锁。
    • 事物默认是自动提交的,可用命令查询:

      • -- 查看自动提交设置
        show variables like 'autocommit';
        -- 关闭自动提交(该设置仅针对当前session)
        set autocommit = 0;
        
        1
        2
        3
        4
        5
        6
        7

        - ``` sql
        -- 开启事务
        begin transaction
        [sql语句]
        -- 释放锁 提交事务
        commit;
    • 支持行级锁和事务

      • 行级锁的读写冲突情况基本与表级锁一致
      • 不走索引的时候就是表级锁,整张表都会被锁住

通过命令给表加锁

1
2
3
4
5
6
7
8
-- 加读/写锁
lock tables [table_name] read | write;
-- 解锁
unlock tables;
-- 让select语句上写锁 在后面加 for update
select * form [table_name] for update
-- 让select语句加读锁 在后面加 lock in share mode (InnoDB有优化,select不加锁,故如果需要加锁可这样做)
select * form [table_name] lock in share mode

MyISAM和InnoDB分别适合的场景

适合MyISAM的场景

  • 频繁执行全表count语句
    • InnoDB不保存行数,count时会全表扫描,MyISAM有一个变量保存全表行数。
  • 对数据进行增删改频率不高,查询非常频繁
    • 增删改会涉及锁表操作,MyISAM性能不强,但是纯查询性能非常高
  • 没有事务的场景

InnoDB适合的场景

  • 数据增删改查都非常频繁的场景
    • 增删改时只是某些行上锁,避免阻塞
  • 可靠性要求较高,要求支持事务的场景

锁的分类

按粒度划分:

表级锁、行级锁、页级锁(表级和行级之间,锁定同一个存储页的相邻几行数据)

按锁级别划分

共享锁、排他锁

按加锁方式划分

自动锁(Mysql自动为我们上的)、显式锁(加了for update等命令强行上的锁)

按操作划分

DML锁(对数据进行操作的锁)、DDL锁(对表结构进行变更的锁)

按使用方式划分

乐观锁(认为数据一般情况下不会造成冲突,所以在数据进行提交的时候才会对数据冲突与否进行检测,通常实现方式为创建version或时间戳信息)

悲观锁(对数据被外界的修改持保守态度,故在整个数据处理过程中都加锁,如全程用排他锁锁定,实现方式为数据库定义的锁)