1、ACID
(1)ACID是靠什么来保证的
ACID(数据库事务正确执行的四个基本要素的缩写)
原子性、一致性、隔离性、持久性
- 原子性
undolog
- 隔离性
MVVC
- 持久性
redolog
- 一致性
由其他三个特性来保证的
2、MVVC
(1)MVCC解决的问题到底是啥
MVCC:多版本并发控制(常常用在数据库里的技术)
数据库并发场景有三种:
读读
不存在任何问题,无需并发控制
读写
有线程安全,可能会造成事务的隔离性问题,可能遇到脏读、幻读、不可重复读
写写
有线程安全问题,可能存在更新丢失问题
脏读(读取未提交数据):脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的,值得注意的是,脏读一般是针对于update操作的。
幻读(前后多次读取,数据总量不一致):事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,成为幻读。
不可重复读(前后多次读取,数据内容不一致):事务A在执行读取操作,由整个事务A比较大,前后读取同一条数据需要经历很长的时间 。而在事务A第一次读取数据,比如此时读取了小明的年龄为20岁,事务B执行更改操作,将小明的年龄更改为30岁,此时事务A第二次读取到小明的年龄时,发现其年龄是30岁,和之前的数据不一样了,也就是数据不重复了,系统不可以读取到重复的数据,成为不可重复读。
不可重复读和幻读到底有什么区别呢?
(1) 不可重复读是读取了其他事务更改的数据,针对update操作
解决:使用行级锁,锁定该行,事务A多次读取操作完成后才释放该锁,这个时候才允许其他事务更改刚才的数据。
(2) 幻读是读取了其他事务新增的数据,针对insert和delete操作
解决:使用表级锁,锁定整张表,事务A多次读取数据总量之后才释放该锁,这个时候才允许其他事务新增数据。
MVCC为事务分配单项增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读事务开始前的数据库快照,所以MVCC可以为数据解决以下问题:
1、在并发读写数据库时,可以在读操作时不阻塞写操作,写操作也不阻塞读操作,提高了数据库并发读写的能力
2、解决脏读、幻读、不可重复读等事务隔离问题,但是不能解决更新丢失问题
(2)MVCC实现原理
3、MySQL的隔离级别有哪些?
https://www.cnblogs.com/fengzheng/p/12557762.html
首先我们来看看隔离级别是个玩意
有四种隔离级别
读未提交(READ UNCOMMITTED)
所有事务都可以看到未提交事务的执行结果
读提交 (READ COMMITTED)
一个事务开始时,只能看到已经提交事务所做的改变
可重复读 (REPEATABLE READ)
???
串行化 (SERIALIZABLE)
通过强制事务排序
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 可能 | 可能 | 可能 |
读提交 | 不可能 | 可能 | 可能 |
可重复读 | 不可能 | 不可能 | 可能 |
串行化 | 不可能 | 不可能 | 不可能 |
4、MySQL索引
https://www.cnblogs.com/zsql/p/13808417.html
(1)为什么要有索引?
一般的应用系统中,读写比例为10:1,而且插入和一般的更新操作很少出现性能问题
生产环境中,我们遇到最多的也是最容易出问题的,是一些复杂的查询操作
索引就是为了进行高速查询
(2)什么是索引?
索引在MySQL中也叫一种“键”,是存储引擎用于快速找到记录的一种数据结构
索引对于良好的性能非常关键,尤其是当表的数据量愈发巨大时,索引对于性能的影响愈发巨大
索引就相当于字典的音序表
(3)索引的原理
(4)索引的数据结构
MySQL主要用到两种结构:B+Tree索引和Hash索引
Inodb存储引擎默认是B+Tree索引
Memory存储引擎默认是Hash索引
(5)聚簇和非聚簇索引的区别
索引存在于磁盘,MySQL的索引类型与存储引擎是相关的,innobd存储引擎数据文件和索引文件全都放在ibd文件中,而myisam的数据文件全都放在myd文件中,索引放在myi文件中,判断条件:数据和索引是否是分开的
(6)索引分类
按数据结构分类可分为:B+tree索引、Hash索引、Full-text索引
按物理存储分类可分为:聚簇索引、二级索引(辅助索引)
按字段特性分类可分为:主键索引、普通索引、前缀索引
按字段个数分类可分为:单列索引、联合索引(复合索引、组合索引)
5、数据库事务、主键和外键的区别
- 事务即用户定义的一个数据库操作序列,这些操作要么全做要全不做,是一个不可分割的工作单位,它具有四个特性,即ACID:原子性、一致性、隔离性、持续性
- 主键是能确定一条记录的唯一标识
- 外键用于与另一张表的关联,是能确定另一张表记录的字段,用于保持数据的一致性
6、简单介绍having和where的区别
用的地方不一样
where可以用于
select
、update
、delete
和insert into values(select * from table where …)
语句中having只能用于
select
语句中执行的顺序不一样
where的搜索条件是在执行语句进行分组之前应用
having的搜索条件是在分组条件后执行的,即如果where和having一起用时,where会先执行,having后执行
子句有区别
where子句中的条件表达式having都可以跟
having子句中的有些表达式where不可以跟,例如集合函数(sum、count、avg、max和min)
总之,WHERE 子句用来筛选 FROM 子句中指定的操作所产生的行。GROUP BY 子句用来分组 WHERE 子句的输出。HAVING 子句用来从分组的结果中筛选行
7、SQL优化技巧
MySQL优化的五个原则:
减少数据的访问
压缩、索引等手段减少磁盘IO
返回更少的数据
只返回需要的字段和数据分页处理,减少磁盘 IO 及网络 IO
减少交互次数
批量 DML 操作,函数存储等减少数据连接次数
减少服务器 CPU 开销
减少数据库排序操作以及全表查询,减少 CPU 内存占用
利用更多资源
使用表分区,可以增加并行操作,更大限度利用 CPU 资源
总结到SQL:
- 最大化利用索引
- 尽可能避免全表扫描
- 减少无效数据的查询
(1)避免不走索引的场景
避免在字段开头模糊查询,会导致数据库放弃索引全表扫描
如:
SELECT * FROM t WHERE username LIKE '%陈%'
改为:
SELECT * FROM t WHERE username LIKE '陈%'
尽量避免使用 in 和 not in,会导致引擎走全表扫描
如果是子查询,可以用 exists 代替
如:
select * from A where A.id in (select id from B);
改为:
select * from A where exists (select * from B where B.id = A.id);
尽量避免使用 or,会导致数据库引擎放弃索引进行全表扫描
可以用 union 代替 or,如下:
SELECT * FROM t WHERE id = 1 OR id = 3
改为SELECT * FROM t WHERE id = 1 UNION SELECT * FROM t WHERE id = 3
尽量避免进行 null 值的判断,会导致数据库引擎放弃索引进行全表扫描
如:
SELECT * FROM t WHERE score IS NULL
改为0值判断:
SELECT * FROM t WHERE score = 0
查询条件不能用 <> 或者 !=
使用索引列作为条件进行查询时,需要避免使用<>或者!=等判断条件
order by 条件要与 where 中条件一致,否则 order by 不会利用索引进行排序
如:
SELECT * FROM t order by age;
改为:
SELECT * FROM t where age > 0 order by age;