数据库基础知识(必读)
参考文章:
事务
1、什么是数据库事务?事务的属性?
一个逻辑单元要成为事务,必须满足ACID的属性,即原子性、一致性、隔离性、持久性
原子性:
一致性:
隔离性:
持久性:
AUTOCOMMIT
2、并发事务带来哪些问题?
脏读:
丢失修改:
不可重复读:
幻读:
不可重复读和幻读区别:
不可重复读的重点是对单条记录的修改,比如多次读取一条记录发现其中某些列的值被修改;幻读的重点在于对多条记录的新增或者删除,比如多次读取一个范围的记录发现记录增多或减少了。
产生并发不一致性问题主要原因是破坏了事务的隔离性,解决方法是通过并发控制来保证隔离性。并发控制可以通过加锁来实现,但是加锁操作需要用户自己控制,相当复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。
3、事务隔离级别有哪些? MySQL的默认隔离级别是?
SQL 标准定义了四个隔离级别:
READ-UNCOMMITTED(未提交读):
最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
READ-COMMITTED(提交读):4、事务隔离级别的RR和RC是怎么实现的
相关语法
1、建表的原则(三大范式)
第一范式(1NF)
第二范式
第三范式
BC范式
2、MySQL外连接知道吗?左外连接和右外连接是什么,有什么区别?什么是内连接,完全连接
外连接分为左外连接和右外连接
左(外)连接,左表(a_table)的记录将会全部表示出来,而右表(b_table)只会显示符合搜索条件的记录。右表记录不足的地方均为NULL
与左(外)连接相反,右(外)连接,左表(a_table)只会显示符合搜索条件的记录,而右表(b_table)的记录将会全部表示出来。左表记录不足的地方均为NULL。
完全连接就是左表和右表都是展示所有记录
内连接是左右表都只显示符合搜索条件的记录
性能优化
1、mysql性能优化
MySQL 索引
索引是在存储引擎层实现的,而不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。
索引的优点
为什么不对表的每个列创建一个索引
索引选取类型
什么场景不适合创建索引
什么样的字段适合创建索引
索引失效:
索引物理分类
聚簇索引和非聚簇索引
聚簇索引的优缺点
索引逻辑分类
单列索引:一个索引只包含一个列,一个表可以有多个单列索引。
组合索引:一个组合索引包含两个或两个以上的列,
前缀索引
对于列的值较长,比如BLOB、TEXT、VARCHAR,就必须建立前缀索引,即将值的前一部分作为索引。这样既可以节约空间,又可以提高查询效率。但无法使用前缀索引做 ORDER BY 和 GROUP BY,也无法使用前缀索引做覆盖扫描。
覆盖索引
覆盖索引的优化及限制
覆盖索引是一种非常强大的工具,能大大提高查询性能,只需要读取索引而不需要读取数据,有以下优点:
1、索引项通常比记录要小,所以MySQL访问更少的数据。
2、索引都按值得大小存储,相对于随机访问记录,需要更少的I/O。
3、数据引擎能更好的缓存索引,比如MyISAM只缓存索引。
4、覆盖索引对InnoDB尤其有用,因为InnoDB使用聚集索引组织数据,如果二级索引包含查询所需的数据,就不再需要在聚集索引中查找了。
限制:
1、覆盖索引也并不适用于任意的索引类型,索引必须存储列的值。
2、Hash和full-text索引不存储值,因此MySQL只能使用BTree。
3、不同的存储引擎实现覆盖索引都是不同的,并不是所有的存储引擎都支持覆盖索引。
4、如果要使用覆盖索引,一定要注意SELECT列表值取出需要的列,不可以SELECT * ,因为如果将所有字段一起做索引会导致索引文件过大,查询性能下降。
最左前缀原则:
顾名思义是最左优先,以最左边的为起点任何连续的索引都能匹配上,
注:如果第一个字段是范围查询需要单独建一个索引
注:在创建联合索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。这样的话扩展性较好,比如 userid
经常需要作为查询条件,而 mobile
不常常用,则需要把 userid
放在联合索引的第一位置,即最左边
同时存在联合索引和单列索引(字段有重复的),这个时候查询mysql会怎么用索引呢?
这个涉及到mysql本身的查询优化器策略了,当一个表有多条索引可走时, Mysql 根据查询语句的成本来选择走哪条索引;
联合索引本质:
当创建(a,b,c)联合索引时,相当于创建了(a)单列索引,(a,b)联合索引以及 (a,b,c)联合索引,想要索引生效的话,只能使用 a和a,b和a,b,c三种组合;当然,我们上面测试过,a,c组合也可以,但实际上只用到了a的索引,c并没有用到!
利用索引中的附加列,您可以缩小搜索的范围,但使用一个具有两列的索引 不同于使用两个单独的索引。复合索引的结构与电话簿类似,人名由姓和名构成,电话簿首先按姓氏对进行排序,然后按名字对有相同姓氏的人进行排序。如果您知道姓,电话簿将非常有用;如果您知道姓和名,电话簿则更为有用,但如果您只知道名不姓,电话簿将没有用处。
所以说创建复合索引时,应该仔细考虑列的顺序。对索引中的所有列执行搜索或仅对前几列执行搜索时,复合索引非常有用;仅对后面的任意列执行搜索时,复合索引则没有用处。
复合索引与单列索引的比较:
2. 有多条件联合查询时最好建联合索引,多个单列索引在多条件查询时优化器会选择最优索引策略,可能只用一个索引,也可能将多个索引全用上! 但多个单列索引底层会建立多个B+索引树,比较占用空间,也会浪费一定搜索效率,
其他知识点:
1、需要加索引的字段,要在where条件中
2、数据量少的字段不需要加索引;因为建索引有一定开销,如果数据量小则没必要建索引(速度反而慢)
3、避免在where子句中使用or来连接条件,因为如果俩个字段中有一个没有索引的话,引擎会放弃索引而产生全表扫描
4、联合索引比对每个列分别建索引更有优势,因为索引建立得越多就越占磁盘空间,在更新数据的时候速度会更慢。另外建立多列索引时,顺序也是需要注意的,应该将严格的索引放在前面,这样筛选的力度会更大,效率更高。
索引的底层实现
1. B+Tree 索引
是大多数 MySQL 存储引擎的默认索引类型。
因为不再需要进行全表扫描,只需要对树进行搜索即可,所以查找速度快很多。
因为 B+ Tree 的有序性,所以除了用于查找,还可以用于排序和分组。
可以指定多个列作为索引列,多个索引列共同组成键。
适用于全键值、键值范围和键前缀查找,其中键前缀查找只适用于最左前缀查找。如果不是按照索引列的顺序进行查找,则无法使用索引。
InnoDB 的 B+Tree 索引分为主索引和辅助索引。主索引的叶子节点 data 域记录着完整的数据记录,这种索引方式被称为聚簇索引。因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。
辅助索引的叶子节点的 data 域记录着主键的值,因此在使用辅助索引进行查找时,需要先查找到主键值,然后再到
主索引中进行查找。
2. 哈希索引
哈希索引能以 O(1) 时间进行查找,但是失去了有序性:
无法用于排序与分组;
只支持精确查找,无法用于部分查找和范围查找。
InnoDB 存储引擎有一个特殊的功能叫“自适应哈希索引”,当某个索引值被使用的非常频繁时,会在 B+Tree 索引之
上再创建一个哈希索引,这样就让 B+Tree 索引具有哈希索引的一些优点,比如快速的哈希查找。
3、BST(二叉查找树)
3.4AVL树vsRBtree: avl树是严格平衡树,而rbtree是弱平衡树,都是通过旋转来保持平衡,而在增删节点时,严格平衡树旋转的次数比弱平衡旋转的次数多,当搜索节点的次数远远大于增删节点的次数时,旋转AVL树,当搜索节点的次数与增删节点的次数差不多时选择RBtree效率高。
4、磁盘读取及预读的过程及时间消耗?
5、btree定义?
2.若根不是叶子结点,则根节点至少有两个子树
3.分支节点至少拥有m/2棵子树(除根和叶子)
4.所有叶子节点都在同一层,这些叶子结点不存储有效的信息
6、为什么btree查找效率高?
7、btree节点如何定义?vs二叉搜索树
8、 b+tree 与B树的区别
9、 为什么b+tree比btree更适合做文件的索引、数据库索引?
1.btree在提高磁盘 io 性能同时并没有解决元素遍历效率低下的问题,b+tree只要遍历叶子节点就可遍历整棵树。2.在数据库中基于范围的查找很频繁,btree每次都要从根节点查,效率低。b+tree只要找到范围左边界的叶子结点,可以顺着叶子结点,找到相应范围的所有元素。
由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当
补充
真实数据库中的B+树应该是非常扁平的,也就是说高度非常小,也就说叉数非常多,每个结点的字树非常多,而且B+树的索引节点是非常小的,一次性可以加载到内存,这样就可以用少量的内存换取只需一次访存即可获取到数据的恐怖效率。
B+树的叉数可以达到1000多叉,存储 22G 容量的表高度也才3层,一次访存即可获取数据。
10、b+树和b树分别有什么应用
11、hashmap为什么用红黑树不用b树
4. 解释一下什么是池化设计思想。什么是数据库连接池?为什么需要数据库连接池?
池话设计应该不是一个新名词。我们常见的如java线程池、jdbc连接池、redis连接池等就是这类设计的代表实现。这种设计会初始预设资源,解决的问题就是抵消每次获取资源的消耗,如创建线程的开销,获取远程连接的开销等。就好比你去食堂打饭,打饭的大妈会先把饭盛好几份放那里,你来了就直接拿着饭盒加菜即可,不用再临时又盛饭又打菜,效率就高了。除了初始化资源,池化设计还包括如下这些特征:池子的初始值、池子的活跃值、池子的最大值等,这些特征可以直接映射到java线程池和数据库连接池的成员属性中。——这篇文章对池化设计思想介绍的还不错,直接复制过来,避免重复造轮子了。
数据库连接本质就是一个 socket 的连接。数据库服务端还要维护一些缓存和用户权限信息之类的 所以占用了一些内存。我们可以把数据库连接池是看做是维护的数据库连接的缓存,以便将来需要对数据库的请求时可以重用这些连接。为每个用户打开和维护数据库连接,尤其是对动态数据库驱动的网站应用程序的请求,既昂贵又浪费资源。在连接池中,创建连接后,将其放置在池中,并再次使用它,因此不必建立新的连接。如果使用了所有连接,则会建立一个新连接并将其添加到池中。连接池还减少了用户必须等待建立与数据库的连接的时间。
这种设计会初始预设资源,解决的问题就是抵消每次获取资源和释放资源造成的开销。连接池也是这样,预先创建好一个连接池,在池中创建一定数量的连接,每当用户需要连接数据库,就从池中取出一个连接,使用完毕之后放回池中,这既可以减少连接创建和释放的开销,便于连接的管理,也可以降低用户等待数据库的延迟。
攻击
sql注入攻击
简介:
用户名:1 密 码:1' OR '1'='1 那么程序接收到参数后,SQL语句就变成了:SELECT * FROM user WHERE name = '1' and password= '1' OR '1'='1 ';
用户名:1'; DROP DATABASE root;-- 密码:1 那么程序接收到参数后,SQL语句就变成了:SELECT * FROM user WHERE name = '1'; DROP DATABASE root;--and password= '1';
解决办法:
MySQL 的体系结构
连接池:
管理工具和服务:
SQL接口:
解析器:
优化器:
缓存器:
存储引擎
MyISAM存储引擎
由于该存储引擎不支持事务、也不支持外键,所以访问速度较快。因此当对事务完整性没有要求并以访问为主的应用适合使用该存储引擎。
InnoDB存储引擎
mysql 5.5版本以后默认的存储引擎
由于该存储引擎在事务上具有优势,即支持具有提交、回滚及崩溃恢复能力等事务特性,他在运行时会在内存中建立缓冲池,用于缓冲数据和索引。支持行锁,并发度高。主键索引为聚簇索引,所以比MyISAM存储引擎占用更多的磁盘空间。因此当需要频繁的更新、删除操作,同时还对事务的完整性要求较高,需要实现并发控制,建议选择。
.ibd文件:存放innodb表的数据文件。
MEMORY
MEMORY存储引擎存储数据的位置是内存,因此访问速度最快,但是安全上没有保障。适合于需要快速的访问或临时表。
BLACKHOLE
黑洞存储引擎,写入的任何数据都会消失,可以应用于主备复制中的分发主库。
存储引擎的另一个知识总结
InnoDB 和 MyISAM 的区别:
InnoDB引擎
InnoDB引擎优点
1、支持事务处理、ACID事务特性; 2、实现了SQL标准的四种隔离级别; 3、支持行级锁和外键约束,行锁优点是粒度小,适用于高并发的频繁表修改,高并发使性能优于 MyISAM。缺点是系统消耗较大。4、可以利用事务日志进行数据恢复。
InnoDB引擎缺点
因为它没有保存表的行数,当使用COUNT统计时会扫描全表。
2、索引不仅缓存自身,也缓存数据,相比 MyISAM 需要更大的内存。
MyISAM引擎
MyISAM 是 MySQL 5.5.5 之前的默认引擎,它的设计目标是快速读取。
MyISAM引擎优点
1.高性能读取;
2.因为它保存了表的行数,当使用COUNT统计时不会扫描全表;
MyISAM引擎缺点
1、锁级别为表锁,表锁优点是开销小,加锁快;缺点是锁粒度大,发生锁冲动概率较高,容纳并发能力低,这个引擎适合查询为主的业务。 2、此引擎不支持事务,也不支持外键。 3、INSERT和UPDATE操作需要锁定整个表;
适用场景
MyISAM适合:(1)做很多count 的计算;(2)插入不频繁,查询非常频繁;(3)没有事务。
InnoDB适合:(1)可靠性要求比较高,或者要求事务;(2)表更新和查询都相当的频繁,并且表锁定的机会比较大的情况。
补充:
OLTP用于存储和管理日常操作的数据;
OLAP用于分析这些数据