数据库
范数
- 1nf 属性值不可再分
- 2nf 消除非主属性的 部分函数依赖 - > 每个非主属性都完全依赖于候选键 避免出现冗余行
- 3nf 消除非主属性的 传递函数依赖
- bcnf 消除主属性的传递函数依赖
连接
- 内连接 inner join 只返回两张表匹配的记录
- 全连接 外连接 (outter) join 返回两张表匹配的记录 与 各自的多余记录
- 左连接 left join 返回A表的多余记录 与匹配的记录
- 右连接 right join 返回匹配的记录 和 B表多余的记录
事务
- 事务是构成单一逻辑单元的操作集合
ACID特性
- A atom 原子性 db的所有操作是一个不可分割的工作单元,保证了事务对数据库的操作不会丢失
- C cosistent 一致性 数据不会因为事务的执行而遭到破坏 保证了事务对数据库操作的正确执行
- I isolate 隔离性 事务并发执行和单独执行的结果是一样的 ,并发的事务不必关心其他事务
- D durable 持久性 事务对db的更新永久的反映在db中 保证了db的可恢复性
并发带来的问题
- 丢失更新 一个事务的更新被另外一个事务的更新替换 A事务先提交修改 B事务后提交修改 覆盖了A事务的修改
- 读脏数据 一个事务可以读取到另外事务未提交的数据 A事务读取 B事务修改的数据,但B未提交,若B撤销 则A读的就是脏数据
- 不可重复读 一个事务内多次读同一个数据 数据前后不一致 A事务多次读同一个数据 同时B事务修改了该数据 A事务发现多次读的同一个数据值不同
- 幻读: 一个事务多次读取数据的条数,数据的条数前后不一致。 事务读到了 其他事务新插入的数据 (1、MVCC加当前读(for update/insert/select) 2通过MVCC+next-key lock解决)
封锁协议
- 一级封锁协议: 写时加x锁 写完释放 避免丢失更新
- 二级: 在1级的基础上加上 读时加s锁 读完释放s锁 避免读脏数据 因为1级加X锁 读的时候加s锁加不上
- 三级: 在1级的基础上加上 读时加s锁 事务结束后释放 避免不可重复读 读的时候 其他事务不能加x锁了
事务的隔离级别
-
读未提交 Read uncommited 避免丢失更新
-
读提交 read commited 避免读脏数据
-
可重复读取 repeatable read 避免不可重复读 (MYSQL 默认)
- 读时不加锁,写加锁
- 事务开始前创建ReadView判断可见性,并从版本链表中找到第一个对当前事务可见的版本读这个版本
- 写加锁
-
可序列化 serializble 事务一个个序列化执行 不能并发执行
-
mysql默认级别是可重复读 不能解决幻读问题 解决幻读要加行间锁
基本锁
- 共享锁 share locks s锁 读锁 多个事务可以对对象T 加s锁 但只能同时读 不能写 此时也不能加 排他锁
- 排他锁 exclusive locks x锁 写锁: 事务A对对象T加x锁后 其他的事务 不能再对此对象加任何锁 直到A释放x锁
封锁带来的问题
- 活锁: 某个事务永远等待 解决方法:先来先服务,提升优先级
- 饿死: 事务序列中的每个事务都要对某数据加s锁 且在短时间内释放 那若又一个事务要对其加x锁 则永远轮不上 解决方法:加s锁前 检查是否有先于自己申请的加x锁的事务
- 死锁:多个事务竞争同一资源 造成相互等待 若无外力推进 则一直等待
SQL 语言的四大类
- 数据库定义语言 创建数据库中的对象 表 视图 索引 聚簇create table view index cluster
- 数控操纵语言 insert update delete
- 数据库控制语言 grant 授权 rollback 回滚到上次提交 commit提交 revoke
- 数据库查询语言: select from where
索引
索引是一种特殊的数据库结构,由表中的一列或者多列组合而成,可以用来快速查询数据表中是否由特定值的记录。通过索引,查数据的时候不用读完所有的记录,只使查询索引列,否则数据库将读取所有的信息进行匹配。
索引应该在哪些字段上建立 更新不频繁 具有区分性(判断 )
- 优点:
- 大大加快数据的查询速度
- 避免排序和临时表
- 可以减少分组和排序的时间
缺点:
- 创建和维护索引较为耗时,在数据进行 增删改的时候 也需要动态维护索引 较为耗时
- 索引 占据磁盘空间
索引失效
带头大哥不能死 中间兄弟不能断,顺序颠倒不影响
- or 查询字段 部分未使用索引
- 使用了左模糊 %
- 查询时 数据类型错误 例如索引的类型是字符串 而查询时写成int类型
- 不符合 左前缀 a ab abc 生效例如index(a,b,c) 不查a 只查bc 或分别查b c 都不能利用索引
- is null 无法使用索引 mysql建议索引不为空
- 索引的列不独立 就是指被索引的列 不能是表达式的一部分 不能是函数的参数
- 范围查询会失效
explain 分析
- 如何查看是否生效 sql语句加上explain可以进行查询分析
- 表的读取顺序数据
- 读取操作的操作类型
- 哪些索引可以使用
- 哪些索引被实际使用
- 表之间的引用
- 每张表有多少行被优化器查询
哈希表
-
哈希函数的构造方法:
-
直接定址法 地址大小要等于关键字集合
-
伪随机数法 (用于关键字长度不同)
-
平方取中法(取中间几位)
-
除留余数法 除的这个数 最好是个质数
-
解决冲突的方法:
-
开放定址: 线性探测再散列 平方探测再散列
-
链地址法(拉链法)
-
再散列法
聚簇索引
- 主键一定是聚簇索引 聚簇索引会存整行数据
- 联合索引 只存索引字段和主键 当查询非索引字段时 要回表 查询聚簇索引找到要查询的字段
B+树
- InnoDB
- 非叶子节点只存储key,叶子节点只存储记录(叶子节点内部数据是顺序存储的),叶子节点之间用链表连起来
- 由于叶子节点之间使用链表相连,便于整表查询,范围查询
- 查询效率稳定:每次只有查到叶子节点才能查到数据
- 查询效率高:由于非叶子节点只存key,所占的空间较小,因此一个非叶子节点上可以存多个key,查找的时候再使用,最后形成一个又矮又胖的树,在非叶子节点上可以根据二分法找到数据的位置,树又比较矮所以效率高
mysql 建库
- mysql -uroot -p12345 # 输入密码进入mysql
- show databases 显示数据库
- create database databasename 创建数据库
- use databasename 选择数据库
SQL注入
- sql注入就是在用户输入字符串中加入SQL语句,如果设计不良的程序中忽略了检查,这些注入的SQL语句就会被数据库服务器认为是正常的SQL 语句运行,攻击者就会执行计划外的命令 或 访问未被授权的数据
- 如何避免
- 过滤输入内容,校验字符串
- 参数化查询 不会将参数作为sql语句的一部分处理 而是在编译完成后 套用参数运行
- 安全测试 安全审计
- 避免使用动态SQL
- 限制数据库权限
- 避免向用户显示数据库错误
sql 语句
- 获取当前日期 select GETDATE()
Redis
基本数据类型
Redis是非关系型键值数据库,可存储键和五种类型之间的映射
键的类型只能为字符串
值的类型有五种:
- STRING 字符串 整数 浮点数
- 计数器
- LIST 列表 两端压入或弹出
- 可以用于消息队列 lpush rpop写入读取消息 最好使用Kafka RabbitMQ等消息中间件
- SET 无序集合
- 实现交集 并集 从而实现共同好友
- HASH 键值队的无序散列表
- ZSET 有序集合(跳跃表)
- 可实现有序性操作 实现排行榜
应用:
- 缓存:热点数据放入内存 设置最大使用量 淘汰策略保证缓存命中率
- 查找表
- 会话缓存: 使用Redis存储多台应用服务器的会话信息,当服务器不存储用户会话信息时,服务器不再具有状态,用户可以请求任意一个服务器,实现高可用和可伸缩
跳跃表 ZSET底层实现
数据淘汰策略 6种
- noeviction 不淘汰,满了抛出异常
- allkeys-random 对所有数据 随机选择淘汰
- allkeys-lru 对所有数据 将最近最少使用的数据淘汰
- volatile-random 对已设置过期时间的数据 随机选择淘汰
- volatile-lru 对已设置过期时间的数据 lru淘汰 least rencently used
- volatile-ttl 对已设置过期时间的数据 挑选即将过期的数据淘汰
- 4.0 中新增2种 volatile-lfu allkeys-lfu 通过访问频率淘汰 least frquency used
- 可设置键的过期时间,键过期的时候 会自动删除该键