连接mysql: mysql -h ip地址 -u root -p 密码
查看数据库:show databases;
创建数据库:create database mydb character set utf8;
修改数据库编码:alter database mydb character set gbk;
删除数据库: drop database mydb; 不确定是否存在:drop database if exists mydb;
创建表:create table student(
id int,
name varchar(),
age int
);
选择表:select * from user
表常用数据类型:int , double ,decimal(size,type),date , datatime, varchar(size)
查看指定表的建表结构: show create table student;
删除表:drop table
修改表的内容:
Alter talbe student add 'desc' varchar(100) ; 添加新的列
alter table student modify 'desc' varchar(50); 修改列的数据类型(长度)
alter table student change 'desc' description varchar(100); 修改列的名称
alter table student drop description; 删除指定列
rename table student to stu; 修改表的名称
alter table stu character set gbk; 修改表的字符编码
表的增删改查:
- 插入数据: insert into student values(5,'zhangshan',26),(6,'lisi',27);
若要插入空值:使用NULL
- 更新数据:update student set name='lili' where id=1;
- 删除记录: delete from student where id =1 ;
1、什么是主键
拿来做唯⼀标识的字段
2、主键、外键、索引的区别
作⽤:
主键:⽤来保存数据的完整性
外键:主要⽤于和其它表建⽴联系
索引:为了提⾼查询排序的速度
在建表之初就要考拆分逻辑
字段优化:
基础:
(1)设置指定超时时间,超过这个时间的sql语句被称为慢查询
(2)long_query_time:默认10秒
优化
(1)运⾏语句,找到慢查询的sql
(2)查询区分度最⾼的字段
(3)explain:显示mysql如何使⽤索引来处理select语句以及连接表,可以帮助选择更好的索
引、写出更优化的查询语句
(4)order by limit形式的sql语句,让排序的表优先查
(5)考虑建⽴索引原则
(6)了解业务使⽤场景
连接:
将各个表中的记录都取出来进⾏依次匹配,将匹配后的结果发给客户端
笛卡尔积:
连接查询的结果中包含⼀个表的每⼀条记录与另⼀个表中每⼀条记录的组合,这样的查询结果
就是笛卡尔积
⽐如表a有5条记录;表b有6条记录;a和b的笛卡尔积就是30
连接过程
1、确定第⼀个需要查询的表,此表为驱动表
2、从驱动表中取每⼀条符合搜索条件的记录,到接下来的表中查找匹配的记录;驱动表之后
的那个表就叫被驱动表
只需要访问驱动表⼀次,可能会多次访问被驱动表
每获得⼀条满⾜条件的驱动表记录,马上到被驱动表中寻找匹配的记录
内连接:
驱动表中的记录在被驱动表中找不到匹配的记录,那么驱动表的这条记录不会加⼊到最后的结
果中
select * from 驱动表, 被驱动表;
select * from 驱动表 join 被驱动表;
select * from 驱动表 inner join 被驱动表;
select * from 驱动表 cross join 被驱动表;
外连接
驱动表中的记录在被驱动表中找不到匹配的记录,也仍需要加⼊到最后结果中
左外连接:语句左侧的表为驱动表
select * from 驱动表 left join 被驱动表 on 连接条件;
右外连接:语句右侧的表为驱动表
select * from 被驱动表 right join 驱动表 on 连接条件;
对于内连接,驱动表和被驱动表的顺序可以更换;对于外连接,这个顺序不能随意更换
过滤条件
where:
不论内外连接,只要是不符合where⼦句的记录都不会加⼊到最后的结果中
on:
在内连接中与where等价;
在外连接中,如果驱动表中的记录在被驱动表中没有记录可以匹配,该驱动表记录仍会加⼊到结果中,对应的被驱动表字段以null填充
嵌套循环连接
如果有3个表进⾏连接,那么表1和表2完成连接后的结果作为驱动表,将表3作为被驱动表进
⾏连接查询
使⽤索引
在根据驱动表的⼀条记录去被驱动表中查询时,相当于确定搜索条件的单表查询,可以使⽤索引优化单表查询
在被驱动表上使⽤⼆级索引进⾏查询时,可能连接查询的变量和过滤条件都是⼆级索引的部分列,可以不⽤回表直接覆盖索引,所以最好不要⽤ * 作为查询列表,⽽是使⽤真正需要查询的列
嵌套循环连接
减少被驱动表的访问次数
Join Buffer连接缓冲区:在执⾏连接查询前申请⼀块固定⼤⼩的内存,先把若干条驱动表结果集中的记录放在buffer中;在扫描被驱动表时,每⼀条被驱动表的记录与buffer中的多条驱动表记录进⾏匹配
多个事物在并发情况下会出现⼀些经典的问题,如?读、不可重复读、脏读、丢失更新。为了不同程度的解决这些问题,出现了不同的隔离级别,锁就是实现各种隔离级别的⼀种⽅式。
Innodb使⽤表锁还是⾏锁?
对于innodb,绝⼤部分情况应该使⽤⾏锁
使⽤表锁的情况
(1)表⽐较⼤,事务需要更新全部或者⼤部分数据
(2)事务涉及到多个表,⽐较复杂,可能引起死锁,造成⼤量的事务回滚
1、全局锁
全局锁就是对?个数据库实例加锁。典型使⽤场景:全库逻辑备份,即把整个库的
表都select出来存成⽂本
MySQL 提供了⼀个加全局读锁的⽅法,命令是 Flush tables with read lock (FTWRL)。
当你需要让整个库处于只读状态的时候,可以使⽤这个命令,之后其他线程的以下语句会被阻塞:
2、表级锁
MySQL ⾥⾯表级别的锁有两种:
(1)表锁
特点:
注意: lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。
(2)元数据锁(meta data lock,MDL)
MDL 不需要显式使⽤,在访问⼀个表的时候会被⾃动加上。
MDL 的作⽤:保证读写的正确性
你可以想象⼀下,如果⼀个查询正在遍历⼀个表中的数据,⽽执⾏期间另⼀个线程对这个表结构做变更,删了⼀列,那么查询线程拿到的结果跟表结构对不上,肯定是不⾏的。
在 MySQL 5.5 版本中引⼊了 MDL
当对⼀个表做增删改查操作的时候,加 MDL 读锁;
当要对表做结构变更操作的时候,加 MDL 写锁。
读锁之间不互斥,因此你可以有多个线程同时对⼀张表增删改查。读写锁之间、写锁之间是互斥的,⽤来保持变更表结构操作的安全性。因此,如果有两个线程要同时给⼀个表加字段,其中⼀个要等另⼀个执⾏完才能开始执⾏。
事务中的 MDL 锁,在语句执⾏开始时申请,但是语句结束后并不会马上释放,⽽会等到整个事务提交后再释放。(这可能会产⽣死锁的问题)
(3)⾏锁
⾏锁就是针对数据表中⾏记录的锁(也有⼈称为记录锁)。
这很好理解,⽐如事务 A 更新了⼀⾏,⽽这时候事务 B 也要更新同⼀⾏,则必须等事务 A 的操作完成后才能进⾏更新。
特点:
3、加锁规则
加锁规则⾥⾯,包含了两个“原则”、两个“优化”和⼀个“bug”
以上规则是在可重复读隔离级别 (repeatable-read) 下证的。同时,可重复读隔离级别遵俩阶段锁协议,所有加锁的资源,都是在事务提交或者回滚的时候才释放的。如果切换到读提交隔离级别 (read-committed) 的话,就好理解了,过程中去掉间隙锁的部分,也就是只剩下⾏锁的部分。
锁的划分
如果我们想要给某⼀⾏加上共享锁?,⽐如想对 user_id=10的数据⾏加上共享锁,可以像下⾯这样:
SELECT user_id FROM product_comment WHERE user_id = 10 LOCK IN SHARE MODE;
2、排他锁(排它锁也叫独占锁、写锁或 X 锁)
排它锁锁定的数据只允许进⾏锁定操作的事务使⽤,其他事务⽆法对已锁定的数据进⾏查询或修改。
如果我们想要在某个数据⾏上添加排它锁,⽐如针对 user_id=10的数据⾏,则写成如下这
样:
SELECT user_id FROM product_comment WHERE user_id = 10 FOR UPDATE;
另外当我们对数据进⾏更新的时候,也就是INSERT、DELETE或者UPDATE的时候,数据库也会⾃动使⽤排它锁,防⽌其他事务对该数据⾏进⾏操作。
3、共享锁与排他锁
共享锁和排他锁不仅可以锁住⼀⾏,也可以锁住⼀张表,如下所示:
⽐如我们想给 product_comment 在表上加共享锁,可以使⽤下⾯这⾏命令
LOCK TABLE product_comment READ;
如果我们想要对表上的共享锁进⾏解锁,可以使⽤下⾯这⾏命令:
UNLOCK TABLE;
如果我们想给 product_comment 数据表添加排它锁,可以使⽤下⾯这⾏命令
LOCK TABLE product_comment WRITE;
这时只有获得排它锁的事务可以对 product_comment 进⾏查询或修改,其他事务如果想要在
product_comment 表上查询数据,则需要等待。
你可以⾃⼰开两个 MySQL 客户端来模拟下。这时我们释放掉排它锁,使⽤这⾏命令即可
UNLOCK TABLE;
一个最⼩的不可再分的⼯作单元
通常情况下,⼀个事务对应⼀个完整的业务
ACID
1、A 原⼦性(Atomicity)
⼀个事务的所有操作,要么全部完成,要么都没完成,不能结束在中间环节。如果事务在执⾏过程中发⽣错误,会被回滚到事务开始之前的状态
2、C ⼀致性(Consistency)
在事务开始之前以及事务结束之后,数据库的完整性不能被破坏
3、I 隔离性(Isolation)
允许多个并发事务同时对数据进⾏修改和读写的能⼒,它可以防⽌由于多个事务并发执⾏时由于交叉执⾏⽽导致的数据不⼀致
4、D 持久性(Durability)
事务处理结束了以后,对数据的修改是永久的,即使是发⽣了系统故障,数据也不会丢失
1、幂等操作
⽤户对同⼀操作发起⼀次请求或者多次请求的结果是⼀致的,不会因为多次点击⽽产⽣副作⽤
2、lvs负载均衡
Linux virtual server:⼀个实现负载均衡的开源软件项⽬
⽬标: 通过LVS的负载均衡技术与Linux操作系统实现⼀个⾼性能,⾼可⽤的Linux服务器集群
逻辑架构
(1)调度层
(2)server集群层
(3)共享存储
3、分布式锁
将多线程的锁机制应⽤到了分布式的部署环境中
特点
(1)互斥性
(2)可重⼊:同⼀个节点上的同⼀个线程,获取到锁之后还可以两次获取这个锁
(3)锁超时:⽀持锁超时,防⽌死锁
(4)⾼效,⾼可⽤
(5)⽀持阻塞和⾮阻塞
(6)⽀持公平锁和⾮公平锁
公平锁:按照请求加锁的顺序获取锁
⾮公平锁:⽆序获取锁
常⻅分布式锁
(1)MySQL
(2)Redis
(3)ZK(Zookeeper)
LRU(Least recently used)
概念:最近最少使⽤,如果数据最近被访问过,那么将来被访问的⼏率也⾼
实现:
(1)设计⼀个链表来缓存数据
(2)新数据插⼊到链表头部
(3)每当缓存命中(也就是缓存数据被访问),将数据移动到链表头部
当链表满的时候,将链表尾部的数据丢弃
LFU(Latest frequently used)
原理:最不经常使⽤,如果⼀个数据在最近⼀段时间内使⽤次数很少,那么它在将来的⼀段时
间内被使⽤的可能性也很⼩
实现
(1)LFU每个数据块设计⼀个引⽤计数
(2)所有数据块按照引⽤计数排序,具有相同引⽤计数的数据块按照时间排序
(3)新加⼊的数据插⼊到队列尾部
(4)在队列中某⼀个数据被访问,该数据引⽤计数加1,队列重新排序
需要删除数据时,将已排序的列表最后的数据库删除
FIFO(First in first out)
原理:先进先出,如果⼀个数据最先进⼊缓存中,就最早淘汰掉
实现
直接⽤队列实现
5、⼀致性hash算法
作⽤:该算法通常⽤于负载均衡中要求资源被均匀的分布到所有节点上,并且对资源的请求能够快速路由到对应的节点上⾯
特点
(1)平衡性:哈希结果要均匀的分配在整个输出空间中
(2)单调性:当数据发⽣变动的时候,对相同的数据始终映射到相同的节点,或者新增加的缓冲节点中,避免⽆法找到原来的数据
(3)稳定性:当出现节点坏掉或者需要动态扩容时,尽量减少数据的移动
原理
关键词
(1)哈希环:将整个哈希的输出空间设置为⼀个环形区域
(2)设置哈希环
(3)将服务器进⾏哈希,可以考虑使⽤服务器的编号或者ip等作为输⼊,得到⼀个输出值,将该输出值映射到输出空间的环形区域上
(4)对⽤户数据进⾏同样的hash操作,映射在环形区域上。然后让数据按照顺时针⽅向移动,遇到的第⼀个服务器就是它分配的服务器
(5)通过将整个哈希输出空间设置为⼀个环形区别,可以有效的减⼩输出空间的变化对于哈希结果的影响
基本概念:
(1)C(⼀致性):对于分布在不同节点上的数据,如果⼀个节点更新数据之后,其他节点都能读到这个最新的数据
(2)A(可⽤性):⾮故障节点在合理的时间内返回合理的响应
(3)P(分区容错性):出现网络错误,系统还能继续⼯作
CAP不能同时共存:
CA:分布式中⼀般不会选择
CP:CP的代表是Zookeeper,放弃可⽤性,追求⼀致性和容错性
AP:追求分区容错性与可⽤性
BASE理论
Basically Available(基本可⽤):分布式系统在出现故障时,允许损失失部分可⽤功能
Soft State(软状态):允许系统中存在中间状态,这个状态不影响系统可⽤性
Eventually consistent(最终⼀致性):在经过⼀段时间之后,所有节点的数据都会达到⼀致
索引的出现其实就是为了提⾼数据查询的效率,就像书的⽬录⼀样
MySQL 在查询⽅⾯主要就是两种⽅式:
1) 创建索引
create index 索引名 on 表名(列名);
# 也可以有多个列名构成索引(即,组合索引)
2) 删除索引
drop index 索引名 on 表名;
在mysql当中,怎么查看⼀个SQL语句是否使⽤了索引进⾏检索?
索引失效的情况:
注意:
建立索引注意事项
MySQL的索引有⼏种
索引常⻅类型
哈希表适⽤于只有等值查询的场景,⽽不适⽤频繁 区间查找
有序数组
优点:
等值查询 和 区间查询 性能都挺好 (有序数组 适合 查询)
缺点:
有序数组不适合 频繁 增/删 记录的场景 (但是,有序数组不合适 增/删)
Note:
有序数组只适⽤于静态存储引擎,在等值查询和范围(区间)查询场景中的性能⾮常优秀
等值查询:
⼆分(前提是,有序 + 顺序存储),查询时间复杂度 O(log N)
区间查询:
⼆叉搜索树
BST 是为了 保留了 “有序数组” 查询(⼆分,O(logN))性能好的优点,同时解决“有序数组”不适合 增/删 的缺点
BST 查询的时间复杂度:O(log N)
但是,为了维持 O(log(N)) 的查询复杂度,就需要保持这课树是平衡⼆插树。(维护 BST 是AVL 的时间复杂度也是 O(log(N)))
⼆插树是搜索效率最⾼的,但是实际上⼤多数的数据库存储却并不使⽤⼆插树。其原因是,索引不⽌存在内存中,还要写到磁盘上
N 叉树
为了让⼀个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块。那么,我们就不应该使⽤⼆叉树,⽽是要使⽤ “N 叉”树(N 取决于数据块的⼤⼩)
即,通过使⽤ N 叉树 来降低 树的⾼度,即 减少读取磁盘的次数(IO是很慢的),提⾼查询效率
N叉树的特点:
折中考虑了 “查询性能” 和 “读取磁盘的次数”,广泛应⽤于 数据库引擎中
MySQL 中,索引是在存储引?层实现的,⽽且不同存储引?的索引的⼯作⽅式并不⼀样。⽽即使多个存储引擎⽀持同⼀种类型的索引,其底层的实现也可能不同。
InnoDB 的索引模型:
InnoDB 使⽤了 B+ 树索引模型,每⼀个索引在 InnoDB ⾥⾯对应一颗B+ 树
假设建表语句如下,则对应的 2 课索引树(主键 ⾃动创建⼀课;字段 k 创建 ⼀课索引树),
如下所示
create table T
(
id int primary key, # 主键 ⾃动创建索引
k int not null,
name varchar(16),
index (k)
) # 给字段 k 条件 索引
engine=InnoDB;
根据叶⼦节点的内容,索引类型分为主键索引和⾮主键索引:
主键索引的叶⼦节点存的是整⾏数据
在 InnoDB ⾥,主键索引也被称为聚簇索引(clustered index)
优点
使⽤索引可以⼤⼤加快数据的检索速度(⼤⼤减少检索的数据量),这也是创建索引的最主要的原因。
但是注意使⽤索引不⼀定能够提⾼查询性能,因为如果数据库的数据量不⼤,那么使⽤索引也不⼀定能够带来很⼤提升。其余⼤多数情况下,索引查询⽐全表扫描要快。
通过创建唯⼀性索引,可以保证数据库表中每⼀⾏数据的唯⼀性。
缺点
空间消耗,⼀个索引对应的就是⼀颗 b+树,每⼀个节点都是⼀个 16KB ⼤⼩的⻚。占⽤的空间较⼤。
创建索引和维护索引需要耗费许多时间,当对表中的数据进⾏增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低 SQL 执⾏效率。