MySQL数据库高级篇 —— MySQL数据库

MySQL数据库高级篇

    • 一、索引高级
    • 二、数据库日志
      • 1. MySQL物理文件的组成
        • 1.1 日志文件
        • 1.2 数据文件
        • 1.3 其他文件
    • 三、存储引擎
        • 1.1 InnoDB存储引擎
        • 1.2 MyISAM存储引擎
        • InnoDB和MyISAM的区别
    • 四、锁机制
        • 1.1 乐观锁和悲观锁(从策略上划分)
          • 1.1.1 乐观锁
          • 1.1.2 悲观锁
            • 1.1.1.1 行级锁(从粒度角度划分)
            • 共享锁和排它锁(从读写角度划分)
        • 1.2 表级锁(从粒度角度划分)
        • 1.3 页级锁(从粒度角度划分)

一、索引高级

​ 索引(Index)是帮助MySQL高效获取数据的数据结构。 索引本身就是数据结构。

​ 索引的目的在于提高查询效率,可以类比字典。其实索引就说是排好序的快速查找数据结构索引,可以简单理解为排好序的快速查找数据结构。

​ 在数据之外,数据系统还维护着满足特定查找算法的数据结构。这些数据结构以某种方式指向数据。这样就可以在这些数据结构上实现高级查找算法。这种数据结构就是索引。【二叉树,BTree】

​ 索引在**MySQL中也叫“键”,**是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。索引优化应该是对查询性能优化最有效的手段了。**索引能够轻易将查询性能提高好几个数量级。**索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。

索引的原理:索引的目的在于提高查询效率,本质是通过不断的缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方法来锁定数据。

磁盘IO与预读:当进行一次IO时,不光要把当前磁盘地址的数据,还要把相邻的数据也都读取到内存缓冲区,因为**局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快访问到。每一次IO读取的数据我们称为一页(page)。**具体一页有多大数据跟操作系统有关,一般为4KB或8KB。也就是我们读取一页内的数据时候,实际上才发生一次IO,这次理论对于索引的数据结构设计非常有帮助。

MySQL数据库高级篇 —— MySQL数据库_第1张图片

​ 如上图所示,为了加快col2的查找,可以维护一个上图所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在一个复杂度内获取相应数据,从而快速的检索出符合条件的记录。

​ 一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上

​ 我们平常所说的索引,如果没用特别指明,都是B树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种类型的索引之外,还有哈希索引(hash index)等。

B+树,作为B树的升级版。在B树基础上,MySQL在B树的基础上继续改造,使用B+树构建索引。B+树和B树最主要的区别在于非叶子节点是否存储数据的问题。

  • B树:非叶子节点和叶子节点都会存储数据。
  • MySQL数据库高级篇 —— MySQL数据库_第2张图片
  • B+树:**只有叶子节点才会存储数据,非叶子节点至存储键值。**叶子节点之间使用双向指针连接,最底层的叶子节点形成了一个双向有序链表。
  • MySQL数据库高级篇 —— MySQL数据库_第3张图片

​ 优势:类型图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本。

通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗。

​ **虽然索引大大提高了查询速度,同时会降低更新表的速度。**如对表进行insert,update和delete。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。

​ 索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询

索引分类:

  • 普通索引
  • 唯一索引
  • 单列索引
  • 组合索引
  • 全文索引
  • 空间索引

1.哪些情况需要创建索引:

  • 主键自动建立唯一索引

  • 频繁作为查询条件的字段应该创建索引

  • 查询中与其他表关联的字段,外键关系建立索引

  • 频繁更新的字段不适合创建索引,因为每次更新不单单是更新了记录还会更新索引

  • where条件里用不到的字段不创建索引

  • 单继/组合索引的选择问题,(在高并发下倾向创建组合索引)

  • 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度

  • 查询中统计或者分组字段

2.哪些情况不用创建索引:

  • 表记录太少

  • 经常增删改的表:提高了查询速度,同时会降低更新表的速度,如对表进行INSERT,UPDATE和DELETE。 因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件

  • 数据重复且分布平均的表字段,因此应该只为最经常查询和最经常排序的数据列建立索引。

  • 注意:如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。

3.性能分析: **MySQL中有专门负责优化SELECT语句的优化器模块,**主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的Query(疑问)提供他认为最优化的执行计划(他认为最优的数据检索方式,但不见得是DBA认为是最优的,这部分最耗费时间)。

  • MySQL常见瓶颈:CPU:CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候

  • IO:磁盘I/O瓶颈发生在装入数据远大于内存容量的时候

  • 服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统的性能状态。

基本语法:

创建:

create [unique] index indexname on tabname(colname(length));
alter tabname add [unique] index [indexname] on (colname(length))

删除:

drop index[indexname] on tabname

查看:

show index from tabname 

四种方式来添加数据表的索引:

alter table tabname add primary key(col_list);
-- 添加主键,意味着索引值必须是唯一,且不能为null
alter table tabname add unique index_name(col_list); 
-- 创建唯一索引(可以允许为null, 而且null可以出现多次)
alter table tabname add index index_name(col_list);
-- 添加普通索引,索引值可以出现多次
alter table tabname add fulltext index_name(col_list);
-- 指定索引为fulltext,用于全文索引

索引结构:

  • BTree索引

  • Hash索引

  • full-text全文索引

  • R-Tree索引

  • InnoDB支持事务,支持行级别锁定。支持B-tree,Full-text等索引,不支持Hash索引;

  • MyISAM不支持事务,支持表级别锁定,支持B-tree,Full-text等索引,不支持Hash索引;

Explain: 使用explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。explain+SQL语句【后面】。

二、数据库日志

如何保证数据并发访问的一致性和有效性是所有数据库必须解决的一个问题。另外,锁冲突也是影响数据库并发性能的一个重要因素。

MySQL服务器(MySQL Server)由 SQL层存储引擎层构成。

  • SQL层 的主要功能包括权限判断SQL解析功能和查询缓存

    处理等。

  • 存储引擎层(Storage Engine Layer)完成底层数据库数据存储操作

如下图所示,它们都有各自的小模块:

MySQL数据库高级篇 —— MySQL数据库_第4张图片

(1)客户端通过连接/线程处理层来连接MySQL数据库。连接线程处理层主要用来处理客户端的请求、身份验证和数据库安全性验证等。

(2)查询缓存和查询分析器(解释器)是SQL层的核心部分,其中主要涉及查询的解析、优化、缓存以及所有内置的函数、存储过程、触发器、视图等功能。

(3)优化器主要负责存储和获取所有存储在MySQL中的数据,可以把这3层统称为MySQL数据库的SQL层。

MySQL各逻辑块简介:

​ MySQL逻辑架构采用SQL层和存储引擎分离的方式真正实现了数据存储和逻辑业务的分离。MySQL的SQL层从宏观上可以分为3层,事实上SQL层包含了很多子模块。具体如下:

  • 初始化模块
  • 核心API
  • 网络交互模块
  • 服务器客户端交互协议模块
  • 用户模块
  • 访问控制模块
  • 连接管理﹑连接线程和线程管理 ,
  • 转发模块
  • 缓存模块
  • 优化器模块
  • 表变更管理模块
  • 表维护模块
  • 系统状态管理模块
  • 表管理器
  • 日志记录模块
  • 复制模块
  • 存储引擎接口模块

1. MySQL物理文件的组成

1.1 日志文件

​ 在MySQL数据库中,日志文件主要记录了数据库操作信息和错误信息。常用的日志文件包括错误日志、二进制日志、查询日志、慢查询日志和InnoDB引擎在线Redo日志等。

(1)错误日志:Error Log

​ 错误日志文件记录了MySQL Server运行过程遇到的所有严重的错误信息,以及MySQL每次启动和关闭的详细信息。默认情况下,错误日志功能是关闭的,启动时要重新配置–log-error[=file_name]选项,修改错误日志存放的目录和文件名称。

(2)二进制日志:Binary Log

​ 二进制日志文件就是常说的binlog。二进制日志记录了MySQL所有修改数据库的操作,然后以二进制的形式记录在日志文件中,其中还包括**每条语句所执行的时间和所消耗的资源,**以及相关的事务信息默认情况下,二进制日志功能是开启的,启动时可以重新配置–log-bin[=file_name]选项,修改二进制日志存放的目录和文件名称。

(3)查询日志:Query Log

​ 默认的查询日志文件是hostname.log。查询日志记录所有的查询操作,包括所有的select操作信息,体积比较大,开启后对性能有较大的影响,可以通过“–log[=file_name]”选项开启。如果需要跟踪某些特殊的SQL性能问题,可以短暂地打开该功能。

(4)慢查询日志:Slow Query Log

​ 慢查询日志是指**所有SQL执行的时间超过long_query_time变量的语句和达到min_examined_row_limit条件的语句。用户可以针对这部分语句进行性能调优。慢查询日志设置–log-slow_queries[=file_name]选项开启后,将记录日志所在的路径和名称。MySQL系统默认的慢查询日志的文件名是 hostname-slow.log,**默认目录也是data目录。查看慢查询日志可以采用 mysqldumpslow 命令对慢查询日志进行分析。

(5)InnoDB引擎在线Redo日志:InnoDB redo Log

​ InnoDB引擎在线Redo日志记录了InnoDB所做的所有物理变更和事务信息。 通过Redo日志和Undo信息,InnoDB大大加强了事务的安全性。InnoDB在线Redo日志默认存放在data目录下面,可以通过设置 innodb_log_group_home_dir选项来更改日志的存放位置、通过 innodb_log_files_in_group选项来设置日志的数量。

可以通过命令查看有log_的日志文件:

show variables like 'log_%';

MySQL数据库高级篇 —— MySQL数据库_第5张图片

  • log-error(错误日志) 记录启动、运行或停止mysql时候出现的问题。
  • log_queries(查询日志) 记录建立的客户端连接和执行的语句。
  • log_slave_updates (更新日志) 记录更改数据的语句。不赞成使用该日志。
  • log-bin(二进制日志) 记录所有更改数据的语句。还用于复制。
  • log_show_queries(慢日志) 记录所有执行时间超过long_query_time秒的所有查询或不使用索引的查询。

如果数据丢失,可以通过binlog来恢复数据:

mysqlbinlog --stop-date=" " D:\installed\mysql-8.0.17- winx64\data\binlog.000189 | mysql -uroot -p123456

1.2 数据文件

​ MySQL数据库会在data目录下面建立一个以数据库为名字的文件夹,用来存储数据库中的表文件数据。 不同的数据库引擎,每个表的扩展名也不一 样。例如,MyISAM引擎用“.MYD”作为扩展名,InnoDB引擎用“.ibd”,CSV使用“.csv”扩展名。

MySQL数据库高级篇 —— MySQL数据库_第6张图片

​ “.ibd”文件和“.ibdata”文件:这两种文件主要是用来存储InnoDB存储引擎的数据,其中主要包括索引信息。InnoDB存储引擎采用这两种数据文件,主要是因为InnoDB存储引擎的存储方式能够通过配置来决定是采用共享表空间还是独享表空间的存储方式存储数据

  • 采用共享表空间的方式存储数据,就会采用ibdata文件来存储,所有的表共同使用一个或者多个ibdata文件。
  • 采用独享表空间的方式存储数据,就会采用ibd文件来存储。

1.3 其他文件

​ MySQL数据库系统除了日志文件、数据文件外,还包括其他一些文件,例如系统配置文件、pid文件、socket文件等。

三、存储引擎

​ 数据库存储引擎是数据库底层软件组件,数据库管理系统(DBMS)**使用数据引擎进行创建、查询、更新和删除数据操作。**不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以获得特定的功能。现在许多同的数据库管理系统都支持多种不同的数据引擎。MySQL的核心就是存储引擎。

​ MySQL提供了多个不同的存储引擎,包括处理事务安全表的引擎和处理非事务安全表的引擎。在MySQL中,不需要在整个服务器中使用同一种存储引擎,针对具体的要求,可以对每一个表使用不同的存储引擎。 MySQL 8.0支持的存储引擎有InnoDB、MyISAM、Memory、Merge、 Archive、Federated、CSV、BLACKHOLE等。

查询MySQL所有的存储引擎

show engines;

MySQL数据库高级篇 —— MySQL数据库_第7张图片

1.1 InnoDB存储引擎

MySQL数据库高级篇 —— MySQL数据库_第8张图片

InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键。MySQL 5.5.5之后,InnoDB作为默认存储引擎,主要特性如下:

(1)InnoDB给MySQL提供了具有提交、回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎。 InnoDB锁定在行级并且也在SELECT语句中提供一个类似Oracle的非锁定读。这些功能增加了多用户部署和性能。在SQL 查询中,可以自由地将InnoDB类型的表与其他MySQL表的类型混合起来, 甚至在同一个查询中也可以混合。

(2)InnoDB是为处理巨大数据量的最大性能设计。 它的CPU效率可能是任何其他基于磁盘的关系数据库引擎所不能匹敌的。

(3)InnoDB存储引擎完全与MySQL服务器整合,为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB将它的表和索引存在一个逻辑表空间中,表空间可以包含数个文件(或原始磁盘分区)。 这与MyISAM表不同,比如在MyISAM表中每个表被存在分离的文件中。**InnoDB表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上。

(4)InnoDB支持外键完整性约束(FOREIGN KEY)。 存储表中的数据时,每张表的存储都按主键顺序存放,如果没有显示在表定义时指定主键,InnoDB会为每一行生成一个6B的ROWID,并以此作为主键。

(5)InnoDB被用在众多需要高性能的大型数据库站点上。 InnoDB不创建目录,使用InnoDB时,MySQL将在数据目录下创建一个名为ibdata1的10MB大小的自动扩展数据文件,以及两个名为ib_logfile0和ib_logfile1的5MB大小的日志文件。

1.2 MyISAM存储引擎

​ **MyISAM基于ISAM存储引擎,并对其进行扩展。**它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、 查询速度,但不支持事务。MyISAM的主要特性如下:

(1)在支持大文件(达63位文件长度)的文件系统和操作系统上被支持。

(2)当把删除和更新及插入操作混合使用的时候,动态尺寸的行产生更少碎片。这要通过合并相邻被删除的块以及若下一个块被删除则扩展到下一块来自动完成。

(3)每个MyISAM表最大的索引数是64,这可以通过重新编译来改变。每个索引最大的列数是16个。

(4)最大的键长度是1000B,这也可以通过编译来改变。对于键长度超过250B的情况,一个超过1024B的键将被用上。

(5)BLOB和TEXT列可以被索引。

(6)NULL值被允许在索引的列中,这个值占每个键的0~1个字节。

(7)所有数字键值以高字节优先被存储,以允许一个更高的索引压缩。

(8)每个表一个AUTO_INCREMENT列的内部处理。MyISAM为 INSERT和UPDATE操作自动更新这一列,这使得AUTO_INCREMENT列更快(至少10%)。在序列顶的值被删除之后就不能再利用。

(9)可以把数据文件和索引文件放在不同目录。

(10)每个字符列可以有不同的字符集。

(11)有VARCHAR的表可以固定或动态记录长度。

(12)VARCHAR和CHAR列可以多达64KB。

使用MyISAM引擎创建数据库,将生产3个文件。文件的名字以表的名字开始,扩展名指出文件类型:

  • frm文件存储表定义,

  • 数据文件的扩展名为.MYD(MYData),

  • 索引文件的扩展名是 .MYI(MyIndexx)。

InnoDB和MyISAM的区别

区别:

  1. InnoDB 支持事务,MyISAM 不支持事务。 这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB的重要原因之一;

  2. InnoDB 支持外键,而 MyISAM 不支持。 对一个包含外键的 InnoDB 表转为 MYISAM 会失败;

  3. InnoDB 是聚集索引,MyISAM 是非聚集索引。 聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

  4. InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

  5. **InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。**一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从 MyISAM 变成InnoDB 的重要原因之一;

如何选择:

  1. 是否要支持事务,如果要请选择 InnoDB,如果不需要可以考虑 MyISAM;

  2. 如果表中绝大多数都只是读查询,可以考虑 MyISAM,如果既有读写也挺频繁,请使用InnoDB。

  3. 系统奔溃后,MyISAM恢复起来更困难,能否接受,不能接受就选 InnoDB;

  4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的。如果你不知道用什么存储引擎,那就用InnoDB,至少不会差。

  5. 删除数据库时需要注意什么?

​ 使用DROP DATABASE命令时要非常谨慎,在执行该命令时,MySQL 不会给出任何提醒确认信息。用DROP DATABASE声明删除数据库后,数 据库中存储的所有数据表和数据也将一同被删除,

而且不能恢复。

四、锁机制

MySQL数据库高级篇 —— MySQL数据库_第9张图片

​ MySQL与其他数据库在锁定机制方面最大的不同之处在于,对于不同的存储引擎支持不同的锁定机制。例如,InnoDB存储引擎支持行级锁 (row-level locking),也支持表级锁,默认的情况下是采用行级锁; MyISAM存储引擎采用的是表级锁(table-level locking)。

​ MySQL各存储引擎使用了3种级别的锁定机制:行级锁定,页级锁定和表级锁定。下面分析一下这3种级别的锁机制的特点。

1.1 乐观锁和悲观锁(从策略上划分)

1.1.1 乐观锁

乐观锁:顾名思义就是非常乐观,非常相信真善美,每次去读数据都认为其它事务不会修改数据,总不会发生并发问题,所以因此没有上锁,快乐的读取数据,而只在提交数据的时候判断其它事务是否搞过这个数据了,如果搞过就rollback。乐观锁相当于一种检测冲突的手段,可通过为记录添加版本或添加时间戳来实现

实现:大多数基于数据版本(Version)记录机制实现
特点:总是假设是最好的情况

乐观锁两种实现方式:

	一是使用数据版本(Version)记录机制实现。这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值+1。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。
	乐观锁定的第二种实现方式和第一种差不多,同样是在需要乐观锁控制的table中增加一个字段,名称无所谓,字段类型使用时间戳(timestamp), 和上面的version类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则OK,否则就是版本冲突。

参考文献:https://blog.csdn.net/dhklsl/article/details/87855043

1.1.2 悲观锁

悲观锁:悲观锁和乐观锁就是相反的存在,对其它事务抱有保守的态度,每次去读数据都认为其它事务会对数据进行修改,所以每次读数据的时候都会上锁,直到取出数据。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性,但随之而来的是各种开销。悲观锁相当于一种避免冲突的手段。

实现:大多数情况下依靠数据库的锁机制实现
特点:总是假设是最坏的情况

选择标准如果并发量不大,或数据冲突的后果不严重,则可以使用乐观锁;而如果并发量大或数据冲突后果比较严重(对用户不友好),那么就使用悲观锁

注意: 首先明确一点乐观锁和悲观锁是一种编程策略,并不是数据库具有悲观锁和乐观锁。

1.1.1.1 行级锁(从粒度角度划分)

行级锁:行级锁最大的特点是锁定对象的颗粒度很小,发生锁定资源争用的概率也很小,能够给予应用程序尽可能大的并发处理能力,从而提高一些需要高并发应用系统的整体性能。虽然能够在并发处理能力上有较大的优势,但是行级锁也存在不少弊端

  • 由于行级锁的颗粒度比较小,每次获取锁和释放锁会消耗比较大,因此加锁比较慢,很容易发生死锁。
  • 行级锁定不是MySQL自己实现的锁定方式,而是由其他存储引擎所实现,比如InnoDB存储引擎。InnoDB实现了两种类型的行级锁,即共享锁和排他锁。而在锁定机制的实现过程中为了让行级锁定和表级锁定共享,InnoDB使用了两种内部使用的意向锁,也就是意向共享锁和意向排它锁。
共享锁和排它锁(从读写角度划分)

共享锁(S),也叫读锁。 允许一个事务读一行数据时阻止其他的事务读取相同数据的排它锁【写】。比如事务T对数据对象A加上共享锁,事务T可以读取A但不能修改A,其他事务只能对A加共享锁【可读】,而不能加排它锁【写】,直到事务T释放A上的共享锁。这保证了其他事务可以读取A,但在T释放A上的共享锁之前不能对A做任何修改。

排他锁(X),也叫写锁。 允许获得排他锁的事务更新数据,阻止其他事务取得相同数据的共享锁和排他锁。若事务T对数据A加排它锁,事务T可以读取A,也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。

意向共享锁(IS) 事务打算给数据行加行共享锁。事务在给一个数据行加共享锁前必须先取得该表的IS锁。

意向排他锁(IX) 事务打算给数据行加行排他锁。事务在给一个数据行加排他锁前必须先取得该表的IX锁。

对于共享锁很好理解,就是多个事务只能读取数据不能改数据。

排它锁是一个事务在一行数据上加上排它锁后,其他事务不能再加其他的锁。

​ mysql的InnoDB引擎默认update,delete,insert都会自动给涉及到的数据加上排它锁select语句默认不会加任何锁类型。所以通过排他锁的数据行再其他事务中是不能修改的,也不能通过select…for update和lock…锁的方式查询数据,但是可以通过select…语句查询,因为普通查询没任何锁。意向锁都是表锁。

意向锁是InnoDB存储引擎自动加的,属于表锁。 对于普通SELECT语句,InnoDB不会加任何锁,对于INSERT、UPDATE、DELETE语句,InnoDB会自动给涉及的数据加排他锁,InnoDB可以通过以下语句添加共享锁和排他锁:

共享锁:

select * from tabname where ....lock in share mode;

排他锁:

select * from tabname where ....for update; 

​ 用select …in share mode 获取共享锁,主要用在需要数据依存关系时来确认某行记录是否存在,并确保没人对这个记录进行update和delete操作。但是如果当前事务也需要对改记录进行更新操作,则很可能造成死锁。对于锁定行记录后需要进行更新操作的应用,应该使用select…for update方式获得排他锁。

​ InnoDB行锁实现方式:InnoDB行锁是通过给索引上的索引加锁来实现的。这一点mysql与oracle不同就,后者是通过再数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。

​ 在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。

1.2 表级锁(从粒度角度划分)

与行级锁不同的是,表级锁的锁定机制的颗粒度最大,该锁定机制的最大特点是系统开销比较小,由于实现逻辑非常简单,因此带来的系统负面影响最小。由于表级锁一次性将整个表锁定,因此可以很好地避免死锁的问题。表级锁定机制也存在一定的缺陷。由于表级锁的锁定机制颗粒很大,所以发生锁冲突的概率最高,并发度最低。

表级锁与行级锁的区别:

表级锁: 开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

行级锁: 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

​ 在数据库实现资源锁定的过程中,锁定机制的粒度越小,数据库实现的算法越复杂,数据库所消耗的内存越大。不过,随着锁机制粒度越来越小,应用的并发发生锁等待的概率也越来越小,系统整体性能会随之增高。

1.3 页级锁(从粒度角度划分)

​ 页级锁定在MySQL中是比较特殊的一种锁定机制,颗粒度介于行级锁定与表级锁定之间,所以获取锁定所需要的资源开销以及锁提供的并发处理的能力也介于表级锁定和行级锁定之间。

​ 从锁的角度来看,表级锁更适合以查询为主、只有少量按索引条件更新数据的应用,而行级锁适应于有大量按索引条件并发更新,少量不同数据同时又有并发查询的应用。

两种数据引擎的区别:

MySQL数据库高级篇 —— MySQL数据库_第10张图片
不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

行级锁: 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

​ 在数据库实现资源锁定的过程中,锁定机制的粒度越小,数据库实现的算法越复杂,数据库所消耗的内存越大。不过,随着锁机制粒度越来越小,应用的并发发生锁等待的概率也越来越小,系统整体性能会随之增高。

你可能感兴趣的:(数据库,mysql,搜索引擎)