mysql索引和锁

MYSQL索引基础

关于引擎

  • myisam:
    • 只有表锁;只有非聚簇索引,索引和文件分开,辅助索引和主键基本没区别。
  • innodb:
    • 有行锁和表锁,主键是聚簇索引,索引和文件一起,辅助索引指向主键索引。
关于索引结构

主流的是B+数,也有hashCode。
hashCode有点检索效率高,但是缺点也很明显,关于范围排序等都不适用。所以我们重点研究B+。
B+树长这样子:图片我都是到处扣的。
优点:
每个节点有多个子女----->减少层级
叶子是连接起来的----->无须前序搜索(就是不用再回上一节点查,而是沿着这条路往下查)
在这里插入图片描述

关于索引名词

联合索引:复合索引,几个字段组合起来的索引。
聚簇索引:索引和数据放在一起。
索引下推:查询的条件在索引上,减少数据的帅选。
覆盖索引:查询的列都在索引上。

MYSQL索引分析

索引失效的情况

最起码要使用索引字段

  1. 索引一定要按创建顺序来,所以 like '%abc’这种是不生效的,like ‘abc%’ 没其他情况是可以命中的。
  2. 函数操作
  3. not运算,!=运算
  4. or操作字段没有按索引顺序来(复合索引情况下)
  5. 类型不匹配
  6. 数据超过mysql的限制(比如命中数据超过80%,走不走索引意义不大了)
索引创建原则
  1. 不为离散度低
  2. 不为频繁更新
  3. 有复合索引单独再创建
  4. 尽量有序,所以mysql不适合UUID做主键
主要分析

expain:
在这里插入图片描述

概要描述:
    id:选择标识符
    select_type:表示查询的类型。
    table:输出结果集的表
    partitions:匹配的分区
    type:表示表的连接类型
        ALL、index、range、 ref、eq_ref、const、system、NULL(从左到右,性能从差到好)
    possible_keys:表示查询时,可能使用的索引
    key:表示实际使用的索引
    key_len:索引字段的长度
    ref:列与索引的比较
    rows:扫描出的行数(估算的行数)
    filtered:按表条件过滤的行百分比
    Extra:执行情况的描述和说明
            该列包含MySQL解决查询的详细信息,有以下几种情况:
            Using where:不用读取表中所有信息,仅通过索引就可以获取所需数据,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示mysql服务器将在存储引擎检索行后再进行过滤
            Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询,常见 group by ; order by
            Using filesort:当Query中包含 order by 操作,而且无法利用索引完成的排序操作称为“文件排序”
        -- 测试Extra的filesort
        explain select * from emp order by name;
            Using join buffer:改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。
            Impossible where:这个值强调了where语句会导致没有符合条件的行(通过收集统计信息不可能存在结果)。
            Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行
            No tables used:Query语句中使用from dual 或不含任何from子句

SQL优化

优化的主要步骤就是建立索引,所以知道上面的分析后也就差不多问题出在哪里了,当然,还有一些其他方面的知识:

内连接是其他外连接的基础,所以内连接性能并不会好点,但是由于内连接会将多余数据切割掉,所以传输数据会少点,从这方面讲,性能快一点点。

不要主观臆测,子查询和in不一定比EXISTS性能差

 union等查询都会产生临时表,那么在每个子查询应该尽量产生少的数据

复合索引合理要比单索引要好,然后多个索引只用一个木九十受影响行数少的那个

mysql是可以一遍跟新和以便查询的,前提条件是在update打开表之前就完成子查询

排序缓存够就一次排序  否则就分好多次  然后将结果拼接
双行:堆排序字段进行排序,排序万完再去查询对应行
单行:直接一步到位

实际代码中我们改注意什么

  1. 尽量减少表连接,最好是没有
  2. 建立好常用的索引
  3. 查询只要写返回的字段,不要写 *
  4. 尽量避免大字段(如果大字段影响太大,可以分开,点击详情再单独展示大字段内容)
  5. 避免用大字段
  6. 能用整数用整数
  7. 主键如果整数采用无符号
  8. 短的字符串能用char就用char
  9. 一般设置默认值 不要有空
  10. 如果实在有多表复杂查询,尽量拆分,然后异步分而治之处理。

MYSQL锁分类

mysql有很多锁:
乐观锁:多版本控制(MVCC)
悲观锁:提前加锁,抢夺控制权的锁
读写锁:读锁,和写锁
排他锁:自己能更新,其他不能更新,但是能读取,也叫写锁
共享锁:自己不能更新,只能读,其他也只能读。也叫读锁
间隙锁:锁住范围的锁

但是上面这些锁都是锁的名称,还有一些锁名称,除了要了解他们字面意思,重点还得结合数据库运行中的实际场景。

隔离级别和锁的关系

之所以有锁,是为了解决并发中带来的冲突问题:

经典四大问题:

读未提交:能读到没有提交的数据(脏读)----> 针对的是更新
读已提交:能读到提交的数据(不可重复读问题)------> 针对的是更新
可重复度:能重复读取数据(幻读)-------> 针对的是新增,删除
序列化:最高,相当于将执行命令串行化

锁与隔离级别的关系

啥叫隔离级别:

我们将A,B两个事务,当做两个人,他们去操作同一台电脑,他们能互相影响的程度就是隔离级别,就是事务与事务之间操作互相影响和数据可见的程度。

所以隔离级别主要是影响事务的运行,而在事务中主要又影响数据的增删改和读取。
分开讲:

  1. 增删改: 一定都会加锁,主要是排他锁,因此其他数据能读,但是不能修改。

  2. 读:看情况加锁,我们发现隔离级别主要是针对读的,因为改就是你能我不能没啥特别需要隔离的程度,而读不一样:
    读未提交:直接读取数据最新数据,忽略版本,忽略提交中间状态
    读已提交:读取数据提交后的MVCC版本,但凡重复读取又提交的就读取最新提交的(快照读)
    可重复度:读取本事务开始时第一次读取到的MVCC版本,就算再次读取又提交的也读取当前事务第一次的数据(快照读)

上面MVCC是实现这些的核心,多版本控制,简单来说就是数据有两个隐藏字段,每条数据都有版本号,开启事务后还有事务号(为了明确谁拥有锁),数据修改数据的版本号。有了这些版本数据之后,后续的作用就来了:

  1. 首先回滚的数据有了,可根据回滚的版本号回滚数据。
  2. 不同隔离级别下,读取数据不同版本的方案也能实现。

所以隔离级别主要通过锁和多版本控制来实现的。

加锁的类型
  • 数据库会有自己加锁的机制,就像java的锁颗粒度一样,更具不同情况优化
    上面说到,更新会加排他锁,还有手动加共享锁SELECT … FOR UPDATE等。关于排他锁,共享锁,其实这是些大类。他下面还能细分,比如新增数据,数据都没有怎么加锁?这时候数据库会根据条件加间隙锁,他也是排他锁的一部分,但是会锁住范围:
    比如A事务按照 5< age < 10 更新数据,B事务插入一条 age = 8的数据,这时候A事务不提交,B是进不去的。(需要注意的是,间隙锁仅在特定条件下启用,例如在可重复读隔离级别下执行非唯一索引扫描或者Next-Key Locks时才会出现。)
  • 数据库何时锁行,何时锁表
    innodb:锁行主要和索引有关,如果命中索引,那就就锁住对应的索引,从而锁住该行数据。如果没有那就是表锁。
    myisam:只有表锁
死锁

多个事务持有对方想要资源的锁,而且互不释放,一直卡死。

理论上:用下面相关命令,按照业务的影响程度,安全的逐个释放持有锁的业务

  • 查看当前所有事务
    select * from information_schema.innodb_trx;
  • 查看加锁信息(MySQL5.X)
    select * from information_schema.innodb_locks;
  • 查看锁等待(MySQL5.X)
    select * from information_schema.innodb_lock_waits;
    -查看加锁信息(MySQL8.0)
    SELECT * FROM performance_schema.data_locks;
    -查看锁等待(MySQL8.0)
    SELECT * FROM performance_schema.data_lock_waits;
  • 查看表锁
    show open tables where In_use>0;
  • 查看最近一次死锁信息
    show engine innodb status;
  • 执行的资源消耗情况
    show PROFILES
  • show processlist 是显示用户正在运行的线程
    show PROCESSLIST

实际上找到之后不管优先级直接干掉,然后优化业务流程,重新发布。(可不能这么说)

MYSQL服务端常用的优化点

大概的说下,一般很多公司不调的,因为直接用的阿里云,即便不是大部分公司不调性能也能应对业务。

mysql配置调优:
          1.配置缓冲区大小innodb_buffer_pool_size,innodb_buffer_pool_instances,innodb_buffer_pool_chunk_size:
                       innodb_buffer_pool_size = innodb_buffer_pool_instances  *  innodb_buffer_pool_chunk_size  (倍数);
                当前配置的innodb_buffer_pool_size是否合适,可以通过分析InnoDB缓冲池的性能来验证。
                可以使用以下公式计算InnoDB缓冲池性能:一般可以设置成物理内存的80%,阿里的一般是75%
                Performance = innodb_buffer_pool_reads / innodb_buffer_pool_read_requests * 100                                                                                                                                                                                                           
                innodb_buffer_pool_reads:表示InnoDB缓冲池无法满足的请求数。需要从磁盘中读取。
                innodb_buffer_pool_read_requests:表示从内存中读取逻辑的请求数。
               例如,在我的服务器上,检查当前InnoDB缓冲池的性能
        show status like 'innodb_buffer_pool_read%';
        InnoDB buffer pool 命中率:
        InnoDB buffer pool 命中率 = innodb_buffer_pool_read_requests / (innodb_buffer_pool_read_requests + innodb_buffer_pool_reads ) * 100
       此值低于99%,则可以考虑增加innodb_buffer_pool_size。
            2.不要让数据存到 SWAP 中
                        SWAP是什么:相当于虚拟内存,映射再磁盘上,会降低mysql的存取速度。加大内存或者禁用swap.
            3.innodb_log_file_size(重做日志大小):发生错误时矫正数据,这个日志先写入缓存然后写入磁盘,太小会频繁刷盘,可以设置大点(但是恢复慢)阿里是内存的10%
            4.innodb_flush_method=O_DIRECT:避免双写入缓冲
            5. innodb_flush_log_at_trx_commit:  确定mysql日志何时刷盘,默认为1,每次事务提交刷盘
                    innodb_flush_method:  则确定日志及数据文件如何write、flush
            7. max_length_for_sort_data: 排序列数据大小阈值
                    max_sort_length: 在排序BLOB或TEXT值时使用的字节数
                    这里还有个知识点:  多路排序和单路排序,多路是内存不够得情况下用的,效率较慢,如果排序缓存超过上面的参数就会启用多路,所以一般未来避免多路也会将上述两个参数设置大些。
 
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
课程简介: 课程总计41课时,从什么是事务讲起,直到分布式事务解决方案,很的0基础基础与提升系列课程。对于难以理解的知识点,全部用画图+实战的方式讲解。 第一部分:彻底明白事务的四个特性:原子性、一致性、隔离性、持久性,用场景和事例来讲解。 第二部分:实战讲数据库事务的6中并发异常:回滚丢失、覆盖丢失、脏读、幻读、不可重复读、MVCC精讲。 第三部分:彻底搞清楚4种事务隔离级别:READ_UNCOMMITTED 读未提交隔离级别、READ_COMMITTED 读已提交隔离级别、REPEATABLE_READ 可重复度隔离级别、SERIALIZABLE 序列化隔离级别 第四部分:彻底搞清楚MySQL的各种:行、表、共享、排它、Next-Key、间隙、X、S、IS、IX、死索引、意向等。 第五部分:彻底搞清楚Spring事务的7种传播级别的原理和使用:PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY、PROPAGATION_REQUIRES_NEW、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER、PROPAGATION_NESTED分布式事务的理论基础:RPC定理、BASE理论、XA协议都是什么,原理是什么,有什么关联关系 第六部分:分布式事务的5种解决方案原理和优缺点:2PC两阶段提交法、3PC三阶段提交法、TCC事务补偿、异步确保策略、最大努力通知策略 第七部分:阿里巴巴分布式事务框架Seata:历经多年双十一,微服务分布式事务框架,用一个Nacos+Spring Cloud+Seta+MySql的微服务项目,实战讲解阿里的分布式事务技术,深入理解和学习Seata的AT模式、TCC模式、SAGA模式。 课程资料: 课程附带配套2个项目源码72页高清PDF课件一份阿里巴巴seata-1.1.0源码一份阿里巴巴seata-server安装包一份

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值