Mysql

常见存储引擎

InnoDB

  • 默认的存储引擎
  • 支持事务、行锁、外键

MyISAM

  • 不支持事务
  • 插入和查询效率高

数据库设计三大范式

在这里插入图片描述

事务

特性 ACID

  • 原子性Atomicity:一个事务中操作,要么全部成功,要么全部失败
  • 一致性Consistency:应用系统从一个正确的状态到另一个正确的状态。即AID为了保证C
  • 持久性Durability:事务一旦提交,不可回滚
  • 隔离性Isolation:事务之间,相互隔离,互不干扰

隔离级别

概念解释

  • 脏读 :一个事务处理过程里读取了另一个未提交的事务中的数据
  • 不可重复读 :一个事务范围内多次查询一个数据,却返回了不同的数据值。由于其他事务修改了数据
  • 幻读:如果执行了两次 SELECT,但第二次返回第一次未返回的行,则该行为“幻影”行。mysql 关于幻读的文档
    在这里插入图片描述

READ UNCOMMITTED

  • 读取其他事务未提交的执行结果

READ COMMITTED

  • 事务可以读取另一个已提交的事务
  • 解决脏读

REPEATABLE READ

  • Mysql默认级别
  • 在同一个事务里, select 的结果总是事务开始时时间点的状态
  • 解决不可重复读问题

MySQL 在RR隔离级别下 解决幻读问题

MVCC 解决 快照读模式的幻读问题
Next-Key Lock 解决当前读模式的幻读问题

快照读

简单查询(不加锁的),都是快照读。
MVCC 会在事务第一次快照读时候生成read view,查询的是事务开始的时候的快照数据,所以就不存在不可重复读和幻读的问题。

MVCC 多版本并发控制

数据有多个版本,每次事务都会生成undo.log
InnoDB 会对每一条数据保存的事务id。
只在RC和RR隔离级别下存在。

  1. insert 数据 name = Jerry,age = 24;
  2. 事务1更新数据 name = tom;
  3. 事务2更新数据 age =30;

InnoDB只查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。
在这里插入图片描述

当前读

lock in share mode(s锁)、for update(x锁)这些需要加锁的查询就是当前读。
就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。

Next-Key Lock

行锁 + 间隙锁的组合

  • 行锁 Record Locks :下文的X锁和S锁。
-- 防止任何其他事务插入、更新或删除值为10的行。
SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 
  • 间隙锁 Gap Locks :
-- 阻止其他事务将值15插入到列 t.c1中,无论列中是否已经有这样的值,
-- 因为范围中所有现有值之间的间隙都被锁定。
SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;
  • Next-Key Lock
-- (-∞,15] 
select * from t where  id <= 15 for update;

SERIALIZABLE

  • 所有读都会加共享锁,并发效率低

行锁

  • 共享锁(也称为 S 锁):允许事务读取一行数据select * from tableName where... lock in share mode;
  • 独占锁 (也称为 X 锁):允许事务删除或更新一行数据select * from tableName where... for update;

表锁

为了实现多粒度的锁机制,InnoDB 还有两种内部使用的意向锁,由 InnoDB 自动添加,且都是表级别的锁

  • 意向共享锁 (IS):事务即将给表中的各个行设置共享锁,事务给数据行加 S 锁前必须获得该表的 IS 锁
  • 意向排他锁 (IX):事务即将给表中的各个行设置排他锁,事务给数据行加 X 锁前必须获得该表 IX 锁

锁之间关系

  • 冲突:两种锁不能同时存在,需要等待锁释放
  • 兼容:两种锁可以同时存在
锁类型XIXSIS
X冲突冲突冲突冲突
IX冲突兼容冲突兼容
S冲突冲突兼容兼容
IS冲突兼容兼容兼容

InnoDB加锁

  • 意向锁,为InnoDB引擎自动控制,用户不需要干预
  • DML操作,自动给涉及的数据集加X锁
  • 查询操作,默认不加任何锁 => 快照读
  • 查询操作可以手动的显式加锁 => 当前读

索引

  • 数据页:InnoDB存储的最小单位
    在这里插入图片描述
  • 回表:非主键索引根据获取到的主键值,再查找其他数据,图中红色部分
    在这里插入图片描述

索引的本质

索引的本质是一种排好序的数据结构

B+树索引

  • 只有叶子节点保存数据,非叶子节点只保存Key信息。这样可以大大降低B+树的高度
  • B+ 树有利于全表扫描。只需要遍历所有叶子节点
  • 每一个索引都会生成一个索引B+树
    在这里插入图片描述

InnoDB索引类型

索引类型

  • 主键索引:主键的索引
  • 普通索引:最普通的索引
  • 唯一索引:索引列的值必须唯一,但允许有空值
  • 联合索引:如果是组合索引,则列值的组合必须唯一
  • 全文索引:适合于模糊搜索

底层类型

  • 主键索引,聚簇索引
    • 叶子节点存储的是数据(数据页)
  • 非主键索引,非聚簇索引
    • 叶子节点存储的是索引字段和主键字段
    • 查询时候可能会需要回表(仅查询索引列时,不需要回表)

InnoDB 索引

联合索引

ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age);

这个联合索引,其实会建出以下三个索引

  • name,city,age
  • name,city
  • name

最左前缀匹配原则

mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配

  • where city= 'dalian' and age = 60 会让索引失效,缺失优先度最高的name
  • where name= 'dalian' and age = 60 会让索引失效,缺失中间字段city
  • where name= 'dalian' and city like '%lian' and age = 20 namecity会走索引,age不会走索引

查询优化器

当对索引中所有列通过"=" 或 “IN” 进行精确匹配时,索引都可以被用到

  • 所以 MySQL 不存在 where 子句的顺序问题而造成索引失效
  • where city= 'dalian' and name= 'dalian' 不会让索引失效,查询优化器会自动优化

注意事项

创建

  • 尽量使用简单类型(数字之类的)
  • 字段尽量为 NOT NULL
  • 字符串索引尽量指定长度,不要对整个列进行索引
  • 区分度越高越好,比如性别字段,区分度太低,不适合索引
  • 索引太多会影响DML新能

使用

  • LIKE 时要 userName%,不要全模糊
  • 字符串要加''
  • 不要在列上计算,会让索引失效
  • 尽量不要使用NOT IN、<>、!= 操作
  • OR 条件
  • 组合索引的使用要遵守最左前缀原则

编码

如果你在使用Mysql或者MariaDB,不要用utf-8,改用utf-8mb4

缓存

MySQL缓存机制简单的说就是缓存sql文本及查询结果,如果运行相同的SQL,服务器直接从缓存中取到结果,而不需要再去解析和执行SQL。如果表更改了,那么使用这个表的所有缓存查询将不再有效,查询缓存中值相关条目被清空。

  • 查询必须是完全相同(逐字节相同)才能够被认为是相同的
  • 更改指的是表中任何数据或是结构发生改变,包括INSERT、UPDATE、 DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE等,也包括那些映射到改变了的表使用MERGE表的查询
  • 对于一些不常改变数据且有大量相同SQL查询的表,查询缓存会节约很大的性能
  • where条件中如包含任何一个不确定的函数将永远不会被cache, 比如current_date, now等
  • 执行SQL里有触发器,自定义函数时,MySQL缓存也是不起作用的

参考文章

  • https://developer.ibm.com/zh/technologies/databases/articles/os-mysql-transaction-isolation-levels-and-locks/
  • https://juejin.cn/post/6844903666420285454
  • https://juejin.cn/post/6931901822231642125
  • https://blog.csdn.net/qq_39390545/article/details/108540362
  • https://tech.meituan.com/2014/06/30/mysql-index.html
  • https://juejin.cn/post/6844903885501530125
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值