数据库
待解决
分库分表
数据库事务
隔离级别
什么是幻读
MVCC
MVCC讲解
mvcc解决了可重复读下的幻读问题
可重复读和幻读:
在可重复读中,该sql第一次读取到数据后,就将这些数据加锁(悲观锁),其它事务无法修改这些数据,就可以实现可重复读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。
数据库的三大范式
第一范式:当关系模式R的所有属性都不能再分解为更基本的数据单位时,称R是满足第一范式,即属性不可分
第二范式:如果关系模式R满足第一范式,并且R得所有非主属性都完全依赖于R的每一个候选关键属性,称R满足第二范式
第三范式:设R是一个满足第一范式条件的关系模式,X是R的任意属性集,如果X非传递依赖于R的任意一个候选关键字,称R满足第三范式,即非主属性不传递依赖于键码
参考
举例子:一个学校的学生,有学号,姓名,家庭住址等(前提是住址不可分),这就是满足第一范式;但如果统计某个省,某个市…有多少学生,这就是个可分的属性,不满足第一范式。
在在这个学生信息后边加上班级,班主任等,这就是不满足第二范式,因为班级,班主任并不因为你一个人而存在,就不具有依赖性,解决方法就是划分为两个表。
第三范式的意思就是,同一个信息不能出现在两个表,比如上面说的(学生信息+班级信息)以及(班级信息)两个表就不具有第三范式。
MySQL的优化方法
通过建立索引对查询进行优化
对查询进行优化,应尽量避免全表扫描
索引
实现方法
一般分为B+树索引和哈希索引。
B+树索引:在B-tree上改进得到,其非叶子节点均为key值,叶子节点是key-data键值对。叶子节点前后相连且有序。
哈希索引:通过对key进行hash(crc/MD5/sha1/sha256…)而将记录存储在不同的bucket种,可以做到常数时间的查找,但要注意哈希冲突的避免(链表法、线性探测、二次探测、公共溢出区的方法)。其中MD5 128位,和sha1/256码都较长不太适合作为hash函数。默认无序。
为什么有了B+树索引还要hash索引?
- B+树默认有序,hash默认无序,所以哈希索引无法用于排序;
- 哈希索引O(1)在速度上毋庸置疑要快于B+树近似O(logn);
- 哈希索引只能进行等值查询(因为他要计算hash(key)再去匹配)而B+树索引可以进行等值、部分前缀、范围查询;
- 底层实现结构不同:B+树是非线性结构,hash桶是线性结构
- 对于某些场景如热点页/活跃查询页,需要借助哈希索引来实现快速查询。
聚焦索引和非聚焦
全文索引
索引和索引结构
这篇文章主要讲Btree索引,以及innodb和mylsam的一些区别,值得看
什么是最左前缀原则?
为什么用 B+ 树做索引而不用哈希表做索引?
1、哈希表是把索引字段映射成对应的哈希码然后再存放在对应的位置,这样的话,如果我们要进行模糊查找的话,显然哈希表这种结构是不支持的,只能遍历这个表。而B+树则可以通过最左前缀原则快速找到对应的数据。
2、如果我们要进行范围查找,例如查找ID为100 ~ 400的人,哈希表同样不支持,只能遍历全表。
3、索引字段通过哈希映射成哈希码,如果很多字段都刚好映射到相同值的哈希码的话,那么形成的索引结构将会是一条很长的链表,这样的话,查找的时间就会大大增加。
主键索引和非主键索引有什么区别?
从图中不难看出,主键索引和非主键索引的区别是:非主键索引的叶子节点存放的是主键的值,而主键索引的叶子节点存放的是整行数据,其中非主键索引也被称为二级索引,而主键索引也被称为聚簇索引。
根据这两种结构我们来进行下查询,看看他们在查询上有什么区别。
1、如果查询语句是 select * from table where ID = 100,即主键查询的方式,则只需要搜索 ID 这棵 B+树。
2、如果查询语句是 select * from table where k = 1,即非主键的查询方式,则先搜索k索引树,得到ID=100,再到ID索引树搜索一次,这个过程也被称为回表。
为什么建议使用主键自增的索引?
但是如果插入的是 ID = 350 的一行数据,由于 B+ 树是有序的,那么需要将下面的叶子节点进行移动,腾出位置来插入 ID = 350 的数据,这样就会比较消耗时间,如果刚好 R4 所在的数据页已经满了,需要进行页分裂操作,这样会更加糟糕。
但是,如果我们的主键是自增的,每次插入的 ID 都会比前面的大,那么我们每次只需要在后面插入就行, 不需要移动位置、分裂等操作,这样可以提高性能。也就是为什么建议使用主键自增的索引。
唯一索引和普通索引的区别
如果某一列的值不重复且不为空,那对这一列加索引就成为了唯一索引。
区别:
从查询过程来说,对于普通索引来说,查找到满足条件的第一个记录(5,500)后,需要查找下一个记录,直到碰到第一个不满足k=5条件的记录。
对于唯一索引来说,由于索引定义了唯一性,查找到第一个满足条件的记录后,就会停止继续检索。
其实这个对于查询效率的影响应该是区别不大。
从更新过程来说,第一种情况是,这个记录要更新的目标页在内存中。这时,InnoDB的处理流程如下:
对于唯一索引来说,找到3和5之间的位置,判断到没有冲突,插入这个值,语句执行结束;
对于普通索引来说,找到3和5之间的位置,插入这个值,语句执行结束。
这样看来,普通索引和唯一索引对更新语句性能影响的差别,只是一个判断,只会耗费微小的CPU时间。
但,这不是我们关注的重点。
第二种情况是,这个记录要更新的目标页不在内存中。这时,InnoDB的处理流程如下:
对于唯一索引来说,需要将数据页读入内存,判断到没有冲突,插入这个值,语句执行结束;
对于普通索引来说,则是将更新记录在change buffer,语句执行就结束了。
而change buffer的主要目的就是将记录的变更动作缓存下来,减少了随机磁盘访问,所以对更新性能的提升是会很明显的。
MySQL的联合索引(又称多列索引)是什么?生效的条件?
数据库的锁
- 共享锁
- 排它锁
- 更新锁
更新锁的意思是:“我现在只想读,你们别人也可以读,但我将来可能会做更新操作,我已经获取了从共享锁(用来读)到排他锁(用来更新)的资格”。一个事物只能有一个更新锁获此资格。 - 意向锁
参考
explain
主从复制数据一致性问题
binary_log+relay_log+I/0thread+SQLthread
操作
inner join、left join、right join、full join
参考
1.MySQL 服务处于运行状态
2.新建数据库的名称为 gradesystem
3.gradesystem 包含三个表:student、course、mark;
student 表包含3列:sid(主键)、sname、gender;
course 表包含2列:cid(主键)、cname;
mark 表包含4列:mid(主键)、sid、cid、score ,注意与其他两个表主键之间的关系。
$ sudo service mysql start
$ mysql -u root
mysql> CREATE DATABASE gradesystem;
mysql> use gradesystem
mysql> CREATE TABLE student(
-> sid int NOT NULL AUTO_INCREMENT,
-> sname varchar(20) NOT NULL,
-> gender varchar(10) NOT NULL,
-> PRIMARY KEY(sid)
-> );
mysql> CREATE TABLE course(
-> cid int NOT NULL AUTO_INCREMENT,
-> cname varchar(20) NOT NULL,
-> PRIMARY KEY(cid)
-> );
mysql> CREATE TABLE mark(
-> mid int NOT NULL AUTO_INCREMENT,
-> sid int NOT NULL,
-> cid int NOT NULL,
-> score int NOT NULL,
-> PRIMARY KEY(mid),
-> FOREIGN KEY(sid) REFERENCES student(sid),
-> FOREIGN KEY(cid) REFERENCES course(cid)
-> );
mysql> INSERT INTO student VALUES(1,'Tom','male'),(2,'Jack','male'),(3,'Rose','female');
mysql> INSERT INTO course VALUES(1,'math'),(2,'physics'),(3,'chemistry');
mysql> INSERT INTO mark VALUES(1,1,1,80),(2,2,1,85),(3,3,1,90),(4,1,2,60),(5,2,2,90),(6,3,2,75),(7,1,3,95),(8,2,3,75),(9,3,3,85);