mysql and redis简化版

发布于:2025-04-03 ⋅ 阅读:(16) ⋅ 点赞:(0)

4、mysql架构

开始编程语言进行调度,获取连接池,调用类型DML(操作数据),DDL(操作表)选择引擎,mysql默认inodb,读取磁盘。

5、sql约束

约束类型

描述

NOT NULL

确保某列的值不能为 NULL。

UNIQUE

确保某列或某些列的值唯一,不能重复。

PRIMARY KEY

唯一标识表中的每一行记录,隐含了 NOT NULL 和 UNIQUE。

FOREIGN KEY

保证引用关系的完整性,用于维护两个表之间的关联性。

CHECK

确保字段的值满足特定的条件。

DEFAULT

为字段设置默认值,在未显式赋值时会使用默认值。

INDEX

提升查询效率,不是完整性约束,但常用于快速检索数据。

6、mysql数据类型介绍

  • 整数:tinyint 一个字节 smallint 两个字节 ==int== 4个字节 ==bigint== 8个字节
  • 小数:float 单精度 double 双精度 decimal 可以指定小数的位数 可以设置长度 10,2 表示总长度为10位小数位为2位
  • varchar  可变长度    指定长度表示最大长度,该列的数据按照实际长度进行存储  这种可变长度最大的优势就是节省空间
  • char  定长:该列下所有数据按照统一的长度进行存储,如果数据长度不够则补充空格,这种类型的优势是查询的效率非常高
  • text:也属于文本的一种,一般是用来保存大文本信息
  • date、datetime:DATE 类型只存储日期,而 DATETIME 类型存储日期和时间。

7、增删改查语法

  • select 内容 from  表名   where 条件
  • insert into 表名 (字段名1,字段名2,。。。。) values(值1, 值2,.....)
  • delete from 表名 [where 条件]
  • update 表名 set 字段名1=值1,.... where 条件
  • 建表:CREATE TABLE students ( id INT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(50) NOT NULL , gender CHAR(1) NOT NULL DEFAULT '男', telephone CHAR(11) NOT NULL UNIQUE KEY )

    删除表:drop table 表名

    修改表的结构:ALTER TABLE students ADD COLUMN age INT

    删除表数据不删结构:truncate

8、事物

8.2、四个特征

  • 原子性:不可再分,(undo日志)
  • 一致性:从一种一致状态切换到另一种
  • 持久性:redolog的日志保证的
  • 隔离性:一个事务在执行的过程不应该受到其他事务的影响
  • 8.4、读锁和写锁

  • 读锁:是共享的,多个事物可以共同获取一把锁, 但不允许写入数据
  • 写锁:阻塞其他的读锁和写锁
  • 串行化底层原理就是加了一把锁

8.3、隔离级别

  • 读未提交:一个事务可以读取到另一个事务暂未提交的数据,会出现"脏读"问题

  • 读已提交:[在同一个事务期间对同一个数据先后读取的结果不一致]

  • 可重复读:”幻读“的问题,幻读当另一个插入了提交,另一个select不到,可通过upload修改

  • 串行化 :当一个客户端访问数据库,而没有commit是另一个无法进行操作

8.5、mvcc

定义:

解决并发冲突问题,通过undo log版本记录链,形成一条日志多个版本,读历史快照旧数据,写是最新数据

进行数据操作,会有连个隐藏字段,数据链指向的是操作之前的数据(数据链),如果需要回滚,会读取之前数据。

使用undo log记录上一条日志,如果需要回滚

有一个事物id,trx_id 和回滚指针 ,mvcc解决读已提交,通过版本找到最新的数据

8.6、不可重复读,读到最开始的快照数据,进行数据处理,而数据已经改变怎么解决。

使用乐观锁,加一个版本,每次修改更行版本,根据版本更新

使用悲观锁,直接用最新数据更新 

8.7、各事物具体应用场景

可重复读

多条查询语句需要开启事物,如统计报表,需要各个数据都是同一时刻

读已提交

不需要同一时间,对性能并发要求较高的事物

8.9、怎么实现持久化

redo日志

更新数据,从磁盘读取数据到buffer pool缓存池中,在讲数据写到redo日志文件中国呢,同时有一个线程io将根据空闲时间更新的数据写入磁盘(如果发生宕机,会通过redo日志恢复)

为什么不直接写入磁盘:

(磁盘顺序写很快比如,rabbitmq,kafka),但这里面是随机写,日志是顺序写

为什么不能idb磁盘顺序写,每个表的idb文件都不同,数据可能突然操作a表又操作b表,所以无法顺序写 

update 更新流程

判断buffer pool缓存池是否有记录,如果没有从ibd获取加载到缓存池中

同步协redo日志 

存储idb会有一个ibd线程随机写入

11、sql优化

11.1、explain执行计划

语法:explain+sql

id

  • id列结合table列,可以查看表的加载顺序

  • id相同,按table列从上到下顺序加载

  • id列不同,id值越大越先被加载

 type

index(全索引扫描)和all(全硬盘扫描、没用上索引)需要优化

效率从好到次:system>const(主键查询)>eq_ref(多表连接中被驱动表的连接列上有primary key或者unique index的检索)>ref(非主键非唯一索引等值扫描)>range(范围查询)>index>all

SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts
最好。
说明:
1)consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
2)ref 指的是使用普通的索引(normal index)。
3)range 对索引进行范围检索。
反例:explain 表的结果,type=index,索引物理文件全扫描,速度非常慢,这个 index 级
别比较 range 还低,与全表扫描是小巫见大巫。

possible_keys

> 理论上会用到哪些索引

 keys

> 实际上用到的索引

rows

当前查询,扫描了多少行数,也是性能评估的重要依据

extra

sql排序是查看

Using index(索引排序效率高)

Using filesort(文件排序效率低)

Using temporary(分组排序效率较低)走索引分组高

Using where(条件排序效率较低)

11.3、sql优化操作 

使用count只能用count(*)*会统计值为null,count列明不会统计null

最左前缀法则:where a=? and b=? ,a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即
可,使用最频繁的一列放在最左边。(mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配),不包括in

比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,因为c字段是一个范围查询,它之后的字段会停止匹配。如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

索引列不能运算:where left(e.name,4)='Lucy' 改为:where e.name like 'Lucy%' 

                                 where salary*12>120000 改为:where salary>120000/12

索引列类型自动转换:-- explain select * from employee where name='250'
                                        -- explain select * from employee where name=250(name为string)

!=、ont in索引失效: where e.name!='Lucy'  、 where e.name not in ('Lucy')

非空判断失效:where e.name is not  NULL、where e.name is   NULL 改为:将null字段为-1或其他

模糊查询:只有右模糊不会失效 where e.name like 'Lu%'

少用or

order by  group by 优化最左前缀法

12.6、为什么建议使用自增长主键作为索引?

在插入过程中尽量减少页分裂

14、日志区别

binlog

主从复制:主库会将写入的变更记录到 Binlog,供从库同步。

数据恢复:用于基于时间点的增量恢复(如在崩溃后恢复到某个时间点)。

特点

• 是 Server 层 的日志,独立于存储引擎。

• 记录的是 逻辑日志,表示数据变更的具体 SQL 操作,例如 INSERT、UPDATE 等。

• 按顺序追加写入。

持久性

• Binlog 的写入通常是延迟提交,可能与事务完成不完全同步。

作用范围

全局范围,记录数据库的所有变更。

• redolog

写入时机

• 在事务提交前,必须确保 Redo Log 已经写入磁盘。

作用范围

局部范围,仅适用于 InnoDB 存储引擎。

主要用于保证事务的持久性,支持事务的崩溃恢复,它记录的是物理数据层的修改操作。

• undolog

用途

• 支持 事务回滚:用于撤销事务的修改,恢复数据到之前的状态。

• 实现 MVCC(多版本并发控制):保留数据的历史版本供读操作使用。

主要用于事务回滚,保证事务的隔离性,它记录的是反向的操作。

特点

• 是 InnoDB 存储引擎 的日志。

• 记录的是 逻辑日志,表示如何撤销某个操作(如将插入改为删除,将更新改为还原为旧值)。

• 与事务绑定,事务完成后可以释放空间(或延迟清理)。

写入时机

• 在事务执行过程中实时写入。

作用范围

• 局部范围,仅适用于 InnoDB 存储引擎。

 1、数据类型

  • string
  • 底层

增删改查

  • set key value
  • get key
  • del k
  • strlen k 

加减

取v中特定位置数据

  • getrange name 0 -1
  • getrange name 0  1
  • setrange name 0 x

设置过期时间

在分布式系统里面可以使用如下命令实现分布式锁

  • setnx(set if not exist)
  •     如果返回1:设置成功
  •     如果返回0:设置失败
  • List 有序、可重复

  • lpush num 1 2 3 4 5
  • rpush num2 1 2 3 4 5

弹出(获取数据的同时将数据从list中删除)

  • lpop
  • rpop

  • lrange num 0 -1
  • lrange num2 0 -1

根据下标获取元素

  • LINDEX key index

大小

  • LLEN key

队列:先进先出

栈:先进后出

  • set无序,不可重复

  • sadd ips '192.168.22.1' '192.168.22.2' '192.168.22.2'

  • smembers ips

查看某个元素在集合中是否存在

  • SISMEMBER key member

  • srem ips '192.168.22.1'

大小

  • scard ips #获取set的长度

随机

  • sadd nums 3 4 5 0 9 8 9 0 8 6 
  • srandmember nums 3

随机并移除

  • spop rands 3

交集

并集

  • Hash:hash的key不能重复,如果重复就覆盖

  • hset person name 'jack'
  • hset person age 40

  • hget person name
  • hget person age

存多个

  • hmset person name 'rose' age 12

大小

  • hlen person

判断k是否存在

  • hexists person age
  • Zset:有序,不可重复,通过score来进行排序,score必须是数字

通过score进行排序
zadd hot 300 '华为met10' 10 '苹果10'  19 '小米'
zrange hot 0 -1
zrevrange hot 0 -1

#分数范围过滤
zrangebyscore hot 11 100
zrangebyscore hot 10 100 limit 0 1


#删除
zrem hot '小米'
zcard hot #查看集合的元素个数

3、redis事物

原子性(Atomicity):事务中的所有命令会按顺序执行,但Redis 事务并不支持回滚

单线程执行:事务中的所有命令在执行期间不会被其他命令打断。

不支持回滚:如果事务中某个命令执行失败,不会影响已执行的命令

4、redis为什么不支持事物回滚

redis 只会因为语法错误而失败,如果这些错误不会在入队的时候发现,说明时程序错误造成的

不需要对回滚进行支持,所以redis才非常的快

 5、持久化

7、内存淘汰

实际上Redis定义了几种策略用来处理这种情况:

  • noeviction(默认策略):对于写请求不再提供服务,直接返回错误(DEL请求和部分特殊请求除外)

  • allkeys-lru:从所有key中使用LRU算法进行淘汰,LRU(Least Recently Used)

  • volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰,LRU(Least Recently Used)

  • allkeys-random:从所有key中随机淘汰数据

  • volatile-random:从设置了过期时间的key中随机淘汰

  • volatile-ttl:在设置了过期时间的key中,根据key的过期时间进行淘汰,越早过期的越优先被淘汰

12、缓存击穿

  • 某一个热点key,在失效的一瞬间

13、缓存穿透

  • 非法访问

17、缓存降级

  • Redis服务不可用,或者网络抖动,导致服务不稳定

解决

  • 使用熔断降级策略进行服务熔断降级

19、布隆过滤器

hash碰撞怎么办

用不同的hash算法取模落在不同位置

存在不一定存在,不存在一定不存在

21、redis底层

底层

通过hashtable

hash表:一维数组加二维码链表。(hash,set)

压缩列表:把链表的指针去掉了,用偏移找到位置,类似于数组(zset,hash,list)

整数数组:查询很快,操作很慢(set)

双向链表:(list)

跳表:底层是链表,从左到右依次排序,有点像二分查找。从下往上看  (zset)

22、redis同步mysql先同步redis还是先同步sql

先操作redis

1、如果先修改同步redis 在同步mysql时出现网络原因,其他数据访问redis是新数据,而mysql存储是老数据(问题:数据不一致)

2、如果先删除redis,在同步mysql,在删除redis(要用延迟,是为了避免另一个线程进来删除后同步老数据)(问题:并发时会有一次数据不一致:解决用锁,限制速度不能使用)

先操作mysql

只会出现一次老数据

问题:如果删除失败,可以用重试消息通知