我们首先需要知道的一个大前提是:mysql的锁是由具体的存储引擎实现的。所以像Mysql的默认引擎MyISAM和第三方插件引擎 InnoDB的锁实现机制是有区别的。可根据不同的场景选用不同的锁定机制。

Mysql有三种级别的锁定:表级锁定、页级锁定、行级锁定

一、定义


  • 每次锁定的是一张表的锁机制就是表级别锁定(table-level)。它是MySQL各存储引擎中粒度最大的锁定机制。

二、优缺点


1. 优点

  • 实现逻辑简单,开销小。
  • 获取锁和释放锁的速度快。
  • 由于表级锁一次会将整个表锁定,所以能很好的避免死锁问题。

2. 缺点

  • 由于锁粒度最大,因此出现争用被锁定资源的概率也会最高,致使并发度十分低下。

三、支持存储引擎


  • 使用表级锁定的主要有MyISAM,MEMORY,CSV等一些非事务性存储引擎。

四、表级锁类型


MySQL的表级锁有两种类型:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。

锁模式的兼容性:

  • 对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写操作
  • 对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作

MyISAM表的读操作与写操作之间,以及写操作之间是串行的。当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。

五、如何加表锁


  • 在执行查询语句(select)前,会自动给涉及的所有表加读锁
  • 在执行更新操作(update、delete、insert等)前,会自动给涉及的表加写锁。这个过程并不需要用户干预,因此不需要直接用lock table命令给MyISAM表显式加锁。

显示加写锁:

// 当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。
// 其他线程的读、写操作都会等待,直到锁被释放为止。
// test表将会被锁住,另一个线程执行select * from test where id = 3;将会一直等待,直到test表解锁
LOCK TABLE test WRITE;

显示加读锁

// test表将会被锁住,另一个线程执行select * from test where id = 3;不会等待
// 执行UPDATE test set name='peter' WHERE id = 4;将会一直等侍,直到test表解锁
LOCK table test READ;

显示释放锁:

UNLOCK TABLES;

需要注意的是,在同一个SQL session里,如果已经获取了一个表的锁定,则对没有锁的表不能进行任何操作,否则会报错。

// 锁定test表
LOCK table test WRITE; // 操作锁定表没问题

SELECT * from test where id = 4; // 操作没有锁的表会报错

SELECT * from bas_farm where id =1356

报错:[Err] 1100 - Table 'bas_farm' was not locked with LOCK TABLES。这是因为MyISAM希望一次获得sql语句所需要的全部锁。这也正是myisam表不会出现死锁的原因。

当然,你也不必担心,MyISAM引擎的默认方式是会给同一个session里的所有表都加上锁的,不会麻烦你自己显示操作的。

六、查看表级锁争用情况


执行:show status like ‘table%’;

mysql> show status like 'table%';
+----------------------------+-----------+
| Variable_name | Value |
+----------------------------+-----------+
| Table_locks_immediate | 20708 |
| Table_locks_waited | 0 |
+----------------------------+-----------+

Table_locks_immediate:产生表级锁定的次数;

Table_locks_waited:出现表级锁定争用而发生等待的次数;

如果Table_locks_waited状态值比较高,那么说明系统中表级锁定争用现象比较严重,就需要进一步分析为什么会有较多的锁定资源争用了。

七、优化表级锁定


优化表级锁时的最大问题是:提高并发度

###1. 通过减少查询时间缩短锁定时间

缩短锁定时间的总体原则是:让Query执行时间尽可能的短。

  • 尽量减少大的、复杂的Query,将复杂Query分拆成几个小的Query分步执行;
  • 尽可能的建立足够高效的索引,让数据检索更迅速;
  • 尽量让MyISAM存储引擎的表只存放必要的信息,控制字段类型;
  • 利用合适的机会优化MyISAM表数据文件。

###2. 设置可并发插入:concurrent_insert=2

MyISAM的表锁虽是读写互相阻塞的,但依然能够实现并行操作。MyISAM存储引擎有一个控制是否打开Concurrent Insert(并发插入)功能的参数选项:concurrent_insert,取值范围为0,1,2。

  • concurrent_insert=0,不允许并发插入。
  • concurrent_insert=1,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个线程读表的同时,另一个线程从表尾插入记录。这是MySQL的默认设置;
  • concurrent_insert=2,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录;

所以,我们可通过设置concurrent_insert=2,同时定期在系统空闲时段执行optimize table tableName语句来整理空间碎片,收回因删除记录而没有真正释放的空间,从而提高并发。optimize参考:mysql中OPTIMIZE TABLE的作用及使用

###3. 合理设置读写优先级

MyISAM存储引擎默认是写优先级大于读优先级。即使是写请求后到,写锁也会插到读锁请求之前。

但是,有时像修改文章点击数 操作是不那么重要的,我们希望的是读更快,此时我们可以这样:

UPDATE  LOW_PRIORITY  article SET click_num=134 WHERE id = 823

LOW_PRIORITY使得系统认为update操作优化级比读操作低,如果同时出现读操作和上面的更新操作,则优先执行读操作。

MySQL提供了几个语句调节符,允许你修改它的调度策略

  • LOW_PRIORITY关键字应用于:DELETE、INSERT、LOAD DATA、REPLACE和UPDATE。
  • HIGH_PRIORITY关键字应用于:SELECT、INSERT语句。
  • delayed(延迟)关键字应用于:INSERT、REPLACE语句。

如果你希望所有支持LOW_PRIORITY选项的语句都默认地按照低优先级来处理,那么可能使用**low-priority-updates**选项来启动服务器。然后可通过使用insert HIGH_PRIORITY table.....来把个别我们希望的INSERT语句提高到正常的写入优先级。

Mysql的表级锁的更多相关文章

  1. Mysql 的表级锁和行级锁

    表级锁 MySQL表级锁分为读锁和写锁. 读锁 用法:LOCK TABLE table_name [ AS alias_name ] READ 释放锁使用UNLOCK tables.可以为表使用别名, ...

  2. Mysql的表级锁和行级锁

    表级锁 MySQL表级锁分为读锁和写锁. 读锁 用法:LOCK TABLE table_name [ AS alias_name ] READ 释放锁使用UNLOCK tables.可以为表使用别名, ...

  3. MySQL学习笔记(五):MySQL表级锁和行级锁

    一:概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制.比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking ...

  4. MySQL表级锁和行级锁

    一:概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制.比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking ...

  5. MySQL中的表级锁

    数据的锁主要用来保证数据的一致性,数据库的锁从锁定的粒度上可以分为表级锁,行级锁和页级锁. MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制,比如MyISAM和MEMORY存 ...

  6. [数据库事务与锁]详解五: MySQL中的行级锁,表级锁,页级锁

    注明: 本文转载自http://www.hollischuang.com/archives/914 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的 ...

  7. MySQL行级锁,表级锁,页级锁详解

    页级:引擎 BDB. 表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行 行级:引擎 INNODB , 单独的一行记录加锁 表级,直接锁定整张表,在你锁定期间,其它进程无法对该表进行写 ...

  8. MySQL行级锁、表级锁、页级锁详细介绍

    原文链接:http://www.jb51.net/article/50047.htm 页级:引擎 BDB.表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行行级:引擎 INNODB , ...

  9. mysql 表级锁

    表级锁:分为读锁和写锁: lock tables table_name read;//其他事务只能读,不能加写锁,要等待更新. SESSION 50 执行: mysql> update test ...

随机推荐

  1. prometheus(7)之数据类型与PromQL语法

    Prometheus的四种数据类型 counter (只增不减 计数) Gauge (常规数值 可变化大小) histogram (柱状图 小于上边界的 总数与次数) summary (分位数  小于 ...

  2. Pytorch中stack()方法的理解

    Torch.stack() 1. 概念 在一个新的维度上连接一个张量序列 2. 参数 tensors (sequence)需要连接的张量序列 dim (int)在第dim个维度上连接 注意输入的张量s ...

  3. Django 小实例S1 简易学生选课管理系统 10 老师课程业务实现

    Django 小实例S1 简易学生选课管理系统 第10节--老师课程业务实现 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 课程模块中,老师将要使 ...

  4. scrapy获取汽车之家数据

    1.创建scrapy项目 >scrapy startproject scrapy_carhome 2.找到对应接口 3.创建爬虫文件 > cd scrapy_carhome\scrapy_ ...

  5. SpringCloud升级之路2020.0.x版-37. 实现异步的客户端封装配置管理的意义与设计

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 为何需要封装异步 HTTP 客户端 WebClient 对于同步的请求,我们使用 spri ...

  6. [tc13008]Egalitarianism2

    考虑对于$n-1$个数$a_{i}$,函数$f(x)=\frac{\sum_{i=1}^{n-1}(x-a_{i})^{2}}{n-1}$的最小值恰在$x=\frac{\sum_{i=1}^{n-1} ...

  7. [loj3048]异或粽子

    先对其求出前缀异或和,然后$o(k)$次枚举,每次选择最大值,考虑如何维护可以全局开一个堆,维护出每一个点的最大值的最大值,那么相当于要在一个点中删去一个点再找到最大值将这些删去的点重新建成一颗tri ...

  8. 一文详解 OpenGL ES 3.x 渲染管线

    OpenGL ES 构建的三维空间,其中的三维实体由许多的三角形拼接构成.如下图左侧所示的三维实体圆锥,其由许多三角形按照一定规律拼接构成.而组成圆锥的每一个三角形,其任意一个顶点由三维空间中 x.y ...

  9. 华为9.8笔试题C++

    问题 给出一颗二叉树,每个节点有一个编号和一个值,该值可能为负数,请你找出一个最优节点(除根节点外),使得在该节点将树分成两棵树后(原来的树移除这个节点及其子节点,新的树以该节点为根节点),分成的两棵 ...

  10. 第一章 初始C语言

    第一章 初始C语言 目录 第一章 初始C语言 1. C语言起源 2. 选择C语言的理由 2.1 设计特性 2.2 高效性 2.3 可移植性 2.4 强大而灵活 2.5 面向程序员 3. C语言的应用范 ...