MySQL锁问题

  • 一. 锁概述
  • 二. 锁分类
  • 三. 存储引擎对锁的支持情况
  • 四. MyISAM 表锁
    • ①. 如何加表锁
    • ②. 读锁案例
      • 1. 准备环境
      • 2. 客户端1
    • ③. 写锁案例
    • ④. 结论
    • ⑤. 查看锁的争用情况
  • 五. InnoDB 行锁
    • ①. 行锁介绍
    • ②. 事务及其ACID属性
    • ③. 并发事务处理带来的问题
    • ④. 事务隔离级别
    • ⑤. InnoDB 的行锁模式
    • ⑥. 案例准备工作
    • ⑦. 行锁基本演示
    • ⑧. 无索引行锁升级为表锁
    • ⑨. 间隙锁危害
    • ⑩. InnoDB 行锁争用情况
  • 六. 常用SQL技巧
    • ①. SQL执行顺序
    • ②. 正则表达式使用
    • ③. MySQL 常用函数

一. 锁概述

  • 锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。

  • 在数据库中,除传统的计算资源(如 CPU、RAM、I/O 等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。

二. 锁分类

从对数据操作的粒度分 :

  1. 表锁:操作时,会锁定整个表。

  2. 行锁:操作时,会锁定当前操作行。

从对数据操作的类型分:

  1. 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。

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

三. 存储引擎对锁的支持情况

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

MySQL这3种锁的特性可大致归纳如下 :

四. MyISAM 表锁

  • MyISAM 存储引擎只支持表锁,这也是MySQL开始几个版本中唯一支持的锁类型。

①. 如何加表锁

②. 读锁案例

1. 准备环境

create database demo_03 default charset=utf8mb4;use demo_03;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,'java编程思想','2088-08-01','1');
INSERT INTO tb_book (id, name, publish_time, status) VALUES(NULL,'solr编程思想','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,'田伯光');

2. 客户端1

  • 客户端 一: 获得tb_book 表的写锁

    lock table tb_book write ;
    

  • 客户端 一: 执行查询操作,查询操作执行成功

    select * from tb_book ;
    

  • 客户端 一:查询未锁定的表

  • 客户端 一:更新锁定的表

  • 客户端 二 : 执行查询锁定的表,查询未锁定的表,执行更新操作

  • 当在客户端一中释放锁指令 unlock tables 后 , 客户端二中的 update语句 , 立即执行 ;

③. 写锁案例

  • 客户端 一 : 获得tb_book 表的写锁 , 执行查询操作, 更新操作

    lock table tb_book write ;
    

  • 客户端 二 : 执行查询操作

    select * from tb_book ;
    
  • 当在客户端一中释放锁指令 unlock tables 后 , 客户端二中的 select 语句 , 立即执行 ;

④. 结论

  1. 对MyISAM 表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;

  2. 对MyISAM 表的写操作,则会阻塞其他用户对同一表的读和写操作;

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

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

⑤. 查看锁的争用情况

show open tables;

  • In_user : 表当前被查询使用的次数。如果该数为零,则表是打开的,但是当前没有被使用。

  • Name_locked:表名称是否被锁定。名称锁定用于取消表或对表进行重命名等操作。

show status like 'Table_locks%';

  • Table_locks_immediate : 指的是能够立即获得表级锁的次数,每立即获取锁,值加1。

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

五. InnoDB 行锁

①. 行锁介绍

  • 行锁特点 :偏向InnoDB 存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

  • InnoDB 与 MyISAM 的最大不同有两点:一是支持事务;二是 采用了行级锁。

②. 事务及其ACID属性

  • 事务是由一组SQL语句组成的逻辑处理单元。

  • 事务具有以下4个特性,简称为事务ACID属性。

③. 并发事务处理带来的问题

④. 事务隔离级别

  • 数据库的隔离级别有4个,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏写、脏读、不可重复读、幻读这几类问题。

  • Mysql 的数据库的默认隔离级别为 Repeatable read , 查看方式:
    show variables like 'tx_isolation';

⑤. InnoDB 的行锁模式

InnoDB 实现了以下两种类型的行锁。

  • 共享锁(S):又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。

  • 排他锁(X):又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。

  • 对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);

  • 对于普通SELECT语句,InnoDB不会加任何锁;

  • 可以通过以下语句显示给记录集加共享锁或排他锁

共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE排他锁(X) :SELECT * FROM table_name WHERE ... FOR UPDATE

⑥. 案例准备工作

create table test_innodb_lock(id int(11),name varchar(16),sex varchar(1)
)engine = innodb default charset=utf8;insert into test_innodb_lock values(1,'100','1');
insert into test_innodb_lock values(3,'3','1');
insert into test_innodb_lock values(4,'400','0');
insert into test_innodb_lock values(5,'500','1');
insert into test_innodb_lock values(6,'600','0');
insert into test_innodb_lock values(7,'700','0');
insert into test_innodb_lock values(8,'800','1');
insert into test_innodb_lock values(9,'900','1');
insert into test_innodb_lock values(1,'200','0');create index idx_test_innodb_lock_id on test_innodb_lock(id);
create index idx_test_innodb_lock_name on test_innodb_lock(name);

⑦. 行锁基本演示

select * from test_innodb_lock where id=3;
update test_innodb_lock set name='300' where id=3;
commit;




⑧. 无索引行锁升级为表锁

  • 如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟表锁一样。
  • 由于 执行更新时 , name字段本来为varchar类型, 我们是作为数组类型使用,存在类型转换,索引失效,最终行锁变为表锁 ;

⑨. 间隙锁危害

  • 当我们用范围条件,而不是使用相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据进行加锁; 对于键值在条件范围内但并不存在的记录,叫做 “间隙(GAP)” , InnoDB也会对这个 “间隙” 加锁,这种锁机制就是所谓的 间隙锁(Next-Key锁) 。

⑩. InnoDB 行锁争用情况

show  status like 'innodb_row_lock%';


总结

  • InnoDB存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面带来了性能损耗可能比表锁会更高一些,但是在整体并发处理能力方面要远远由于MyISAM的表锁的。当系统并发量较高的时候,InnoDB的整体性能和MyISAM相比就会有比较明显的优势。

  • 但是,InnoDB的行级锁同样也有其脆弱的一面,当我们使用不当的时候,可能会让InnoDB的整体性能表现不仅不能比MyISAM高,甚至可能会更差。

  • 优化建议:

    • 尽可能让所有数据检索都能通过索引来完成,避免无索引行锁升级为表锁。
    • 合理设计索引,尽量缩小锁的范围
    • 尽可能减少索引条件,及索引范围,避免间隙锁
    • 尽量控制事务大小,减少锁定资源量和时间长度
    • 尽可使用低级别事务隔离(但是需要业务层面满足需求)

六. 常用SQL技巧

①. SQL执行顺序


②. 正则表达式使用

select * from tb_book where name regexp '^j';

③. MySQL 常用函数






MySQL进阶学习---MySQL锁问题相关推荐

  1. 【MySQL进阶】MySQL事务隔离与锁机制底层原理万字总结(建议收藏!!)

    [MySQL进阶]MySQL事务隔离与锁机制底层原理万字总结(建议收藏!!) 参考资料: 美团技术团队:Innodb中事务隔离级别和锁的关系 数据库的锁,到底锁的是什么? 阿里面试:说说一致性读实现原 ...

  2. Mysql进阶学习(二)条件查询

    Mysql进阶学习(二)条件查询 进阶2:条件查询 一.按条件表达式筛选 案例1:查询工资>12000的员工信息 案例2:查询部门编号不等于90号的员工名和部门编号 二.按逻辑表达式筛选 案例1 ...

  3. Mysql进阶学习(五)连接查询(包含sql92标准和sql99标准)

    Mysql进阶学习(五)连接查询(包含sql92标准和sql99标准) 一.进阶6:连接查询 (一).sql92标准 1.等值连接 1.1 等值连接简介 案例1:查询女神名和对应的男神名 案例2:查询 ...

  4. Mysql进阶学习(一)基础查询

    Mysql进阶学习(一) 进阶一:基础查询 1.查询表中的单个字段 2.查询表中的多个字段 3.查询表中的所有字段 4.查询常量值 5.查询表达式 6.查询函数 7.起别名 8.去重 9.+号的作用 ...

  5. Mysql进阶学习(四)分组函数与分组查询

    Mysql进阶学习(四)分组函数与分组查询 一.进阶4:分组函数 1.简单的使用 1.1 SUM 求和 1.2 AVG 求平均值 1.3MIN 最小值 1.4 MAX 最大值 1.5 COUNT求总数 ...

  6. Mysql进阶学习(三)排序查询与常见函数

    Mysql进阶学习(三)排序查询与常见函数 一.进阶3:排序查询 1.语法: 2.特点: 3.排序方式 3.1.按单个字段排序 3.2.添加筛选条件再排序 案例:查询部门编号>=90的员工信息, ...

  7. Mysql进阶学习(六)子查询与分页查询

    Mysql进阶学习(六)子查询与分页查询 进阶7:子查询 1.含义: 2.分类: 3.where或having后面 3.1 特点: 3.2.标量子查询★ 案例1:谁的工资比 Abel 高? 案例2:返 ...

  8. Mysql进阶学习(七)联合查询与DML语言

    Mysql进阶学习(七)联合查询与DML语言 进阶9:联合查询 语法: 特点:★ 案例 DML语言 1.插入语句(insert) 方式一:经典的插入 1.1.插入的值的类型要与列的类型一致或兼容 1. ...

  9. Mysql进阶学习所用到的SQL测试库代码

    Mysql进阶学习所用到的SQL测试库代码 一.`myemployees`库 二.`girls`库 一.myemployees库 /* SQLyog Ultimate v10.00 Beta1 MyS ...

最新文章

  1. 基于fpga的数码管动态扫描电路设计_【至简设计案例系列】基于FPGA的密码锁设计(altera版)...
  2. C++去掉字符串首尾的特殊字符(比如空格)
  3. arraycopy方法的作用_System. arraycopy()入门指南
  4. 2016年12月数据库流行度排行榜
  5. 波纹扩散_C4D_动画amp;RS波纹扩散效果J_014
  6. Apache和Nginx下禁止访问特定的目录或文件
  7. php函数积累第二弹(关于文件操作)
  8. 牛客小白月赛9 论如何出一道水题
  9. SPSS Statistical 软件的使用
  10. 如何解决卸载驱动之后又重新装的问题
  11. 积分上限函数求导总结
  12. 【ubuntu】The following signatures couldn‘t be verified because the public key is not available
  13. 首席新媒体运营黎想教程:3步教你如何做好社群运营
  14. 如何在一夜之间获得成功:我「从无到有」的 5 年 [英文版]
  15. 当我开始爱自己——卓别林
  16. 【软件测试】自动化测试战零基础教程——Python自动化从入门到实战(一)
  17. 【聚水潭SDK使用说明】
  18. android短信接受震动,Android中实现拨打电话、发送短信、响铃、震动和获取当前时间...
  19. JavaEE 项目常见错误汇总
  20. assign 和 weak

热门文章

  1. 码多多ChatAI智能聊天系统更新啦~
  2. 【记录我的作业2】工业机器人职业技能训练——week3RobotStudio纪念币和键盘工作台仿真。
  3. 网页直播英文版上线,跨国企业客户用着很酷哇
  4. java 怎么用二维数组_java二维数组怎么用
  5. FreeBSD下ADSL上网断线自动重拨
  6. qt控件设置图标方法总结
  7. 复选框check的选中、不选中设置以及判断是否选中
  8. 建立一个个人网站部署到github上
  9. windows 10预览版升级win10 7月29 10240.16384
  10. Oracle Data Cloud助力Pinterest征战移动市场