zoukankan      html  css  js  c++  java
  • 【MySQL】锁之MyISAM

    纸上得来终觉浅,绝知此事要躬行。

    锁的分类

    从对数据操作的粒度分 :

    1. 表锁:操作时,会锁定整个表。
    2. 行锁:操作时,会锁定当前操作行。

    从对数据操作的类型分:

    1. 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。
    2. 写锁(排它锁):当前操作没有完成之前,它会阻断其他写锁和读锁。

    MySQL锁

    MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。下表中罗列出了各存储引擎对锁的支持情况:

    存储引擎 表级锁 行级锁 页面锁
    MyISAM 支持 不支持 不支持
    InnoDB 支持 支持 不支持
    MEMORY 支持 不支持 不支持
    BDB 支持 不支持 支持

    特性:

    锁类型 特点
    表级锁 偏向MyISAM 存储引擎,开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
    行级锁 偏向InnoDB 存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
    页面锁 开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

    MyISAM如何加表锁

    MyISAM 在执行查询语句SELECT前,会自动给涉及的所有表加读锁,在执行更新操作UPDATE、DELETE、INSERT前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用 LOCK TABLE 命令给 MyISAM 表显式加锁。

    显式加表锁语法:

    加读锁 : lock table table_name read;
    
    加写锁 : lock table table_name write;
    

    显式解锁语法:

    unlock tables;
    

    虽然MyIASM默认加了表锁,但是我们仍然可以手动加锁,具体通过案例来了解一下加锁之后,我们操作数据库会有什么影响。

    测试数据准备

    在进行测试之前我们需要准备测试环境和相关数据库以及表,并且把MySQL的存储引擎指定为MyISAM,如下先创建一个数据库并切换到数据库:

    create database demo2 default charset=utf8;
    

    接着创建表,本次我们测试的是MyISAM存储引擎,所以要创建表时要指定存储引擎(说明存储引擎是作用于表,而不是作用于数据库,也就是说一个数据库有多个表,而多个表可以使用不同的存储引擎)

    CREATE TABLE `tb_book` (
      `id` INT(11) auto_increment,
      `name` VARCHAR(50) DEFAULT NULL,
      `publish_time` DATE DEFAULT NULL,
      `status` CHAR(1) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=myisam DEFAULT CHARSET=utf8 ;
    
    # 插入数据
    
    INSERT INTO tb_book (id, name, publish_time, status) VALUES(NULL,'高性能MySQL','2088-08-01','1');
    INSERT INTO tb_book (id, name, publish_time, status) VALUES(NULL,'MySQL技术内幕','2088-08-08','0');
    
    CREATE TABLE `tb_user` (
      `id` INT(11) auto_increment,
      `name` VARCHAR(50) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=myisam DEFAULT CHARSET=utf8 ;
    
    # 插入数据
    
    INSERT INTO tb_user (id, name) VALUES(NULL,'张三');
    INSERT INTO tb_user (id, name) VALUES(NULL,'李四');
    

    写锁测试

    仅对加锁的表操作

    Session-1 Session-2
    1.Session-1添加写锁
    2.Session-2读写全部阻塞
    3.Session-1可读可写
    4.Session-1解除写锁 5.Session-1解除锁的同时Session-2解除阻塞执行

    仅对其他表操作

    Session-1 Session-2
    1.Session-1添加写锁
    2.Session-2对其他表可读可写
    3.Session-1无法操作其他表
    4.Session-1解除写锁

    写锁总结

    • 当前用户:只能读写加锁的表,不能读写其他的表
    • 其他用户:阻塞读写加锁的表,能够读写其他的表

    读锁测试

    仅对锁的表操作

    Session-1 Session-2
    1.Session-1加读锁 2.Session-2读取正常
    3.Session-2写入操作阻塞
    4.Session-1读取正常
    5.Session-1写入失败
    6.Session-1释放读锁 7.Session-1在释放读锁的同时Session-2解除阻塞

    仅对其他表操作

    Session-1 Session-2
    1.Session-1加读锁
    2.Session-2可读可写
    3.Session-1无法读写
    4.Session-1释放读锁

    读锁总结

    • 当前用户:只能读加锁的表
    • 其他用户:阻塞写加锁的表,可以读加锁的表,能够读写其他的表

    查询锁的争用情况

    show open tables;
    

    锁的争用情况

    In_user:表当前被查询使用的次数。如果该数为零,则表是打开的,但是当前没有被使用。
    Name_locked:表名称是否被锁定。名称锁定用于取消表或对表进行重命名等操作。

    show status like 'Table_locks%';
    
    
    mysql> show status like 'Table_locks%';
    +-----------------------+-------+
    | Variable_name         | Value |
    +-----------------------+-------+
    | Table_locks_immediate | 139   |
    | Table_locks_waited    | 0     |
    +-----------------------+-------+
    2 rows in set (0.00 sec)
    

    Table_locks_immediate:指的是能够立即获得表级锁的次数,每立即获取锁,值加1。
    Table_locks_waited:指的是不能立即获取表级锁而需要等待的次数,每等待一次,该值加1,此值高说明存在着较为严重的表级锁争用情况。

    总结

    ​简而言之,就是读锁会阻塞写,但是不会阻塞读。而写锁,则既会阻塞读,又会阻塞写。

    此外,MyISAM 的读写锁调度是写优先,这也是MyISAM不适合做写为主的表的存储引擎的原因。因为写锁后,其他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远阻塞。

  • 相关阅读:
    数组练习
    数组
    表达式和语句
    搜索框制作
    操作DOM
    数据类型
    javascript数组属性及方法
    javascript字符串属性及常用方法总结
    css清除浮动float
    vue项目搭建步骤
  • 原文地址:https://www.cnblogs.com/ydongy/p/13092059.html
Copyright © 2011-2022 走看看