Mysql
事务隔离级别
1. 读未提交(read-uncommitted):一个事务可以读取另一个未提交的事务 - 脏读
2. 不可重复读(read-committed):一个事务等待另一个事务提交才能读数据 - 不可重复读
3. 可重复读(repeatable-read):事务开始时不允许修改 - 幻读
4. 串行化(serializable):事务串行化顺序处理,避免出现脏读、不可重复读、幻读,但是效率较低一般不用
事务特性
事务的四个特性是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),简称ACID
1. 原子性说的是数据要么一起成功,要么一起失败,即事务提交(commit)和事务回滚(rollback)。
2. 保证数据库的数据一致性,要在以下两个方面做努力:
a. 利用数据库的一些特性来保证部分一致性需求:比如声明某个列为NOT NULL 来拒绝NULL值得插入等。
b. 绝大部分还是需要我们程序员在编写业务代码的时候来保证。
3. 隔离性的体现,是多个并发事务之间是隔离的,张三给李四转账,如果事务没有提交的话,那么在另外一个session中并不能查看另外一个session未提交的数据。
4. 一个事务一旦提交,它对数据库中数据的改变就应该是持久性的,接下来的其他操作或故障不应该对其有任何影响。要保证持久性很简单,就是每次事务提交的时候,都将数据刷磁盘上,这样一定能保证其安全性。
索引
1. 什么是索引:索引是数据库的目录
2. 索引的优缺点:有点是查询速度快,缺点是增删改慢,因为数据库需要维护索引
3. 索引种类:主键索引、唯一索引、普通索引、联合索引、全文索引
4. 索引为什么快:使用了B+树查询
5. 什么情况需要加索引: 频繁作为查询条件的字段或者与其他表关联的字段
6. 判断索引是否用上:通过explain查询sql执行计划,其中的key就是实际使用的索引
7. 组合索引最左匹配原则:从最左边起连续的索引能匹配上,遇到范围查询(><、!=、in、between、like如果是X%Y%可以)会终止
B+树
1. 特性
a. 非叶子节点只存储key,data都在叶子节点上
b. 叶子节点存储指针
c. 顺序访问指针,提高区间访问性能
2. 与B树的区别
a. B树的每个节点都有key和data
3. 为什么使用B+树存储索引
a. 数据库的性能取决于磁盘IO的次数,B+树本身查询快,相比B树高度更低也就会IO更少
b. 所有叶子节点形成有序链表,便于范围查询
悲观锁
1. 定义:当要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制,悲观锁适用于读少写多的场景
实现:
2. 实现
a. 传统的关系型数据库使用这种锁机制,比如行锁、表锁、读锁、写锁等,都是在操作之前先上锁。
b. Java 里面的同步 synchronized 关键字的实现。
3. 种类
a. 共享锁(shared locks)又称为读锁,简称S锁。顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
b. 排他锁(exclusive locks)又称为写锁,简称X锁。顾名思义,排他锁就是不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁。获取排他锁的事务可以对数据行读取和修改。
乐观锁
1. 定义:乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成并发冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。
2. 实现
a. CAS 实现:Java 中java.util.concurrent.atomic包下面的原子变量使用了乐观锁的一种 CAS 实现方式。
b. 版本号控制:一般是在数据表中加上一个数据版本号 version 字段,表示数据被修改的次数。当数据被修改时,version 值会+1。
表锁
1. 不会出现死锁,发生锁冲突几率高,并发低
2. MyISAM引擎在执行查询语句(select)前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁
行锁
1. 会出现死锁,发生锁冲突几率低,并发高。
2. InnoDB引擎支持行锁,MySQL的行锁是通过索引加载的,行锁是加在索引响应的行上的,要是对应的SQL语句没有走索引,则会全表扫描,行锁则无法实现,取而代之的是表锁
3. 行锁分 共享锁 和 排它锁:对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;对于普通SELECT语句,InnoDB不会加任何锁
调优
1. 优化数据库表结构的设计,避免冗余字段
2. 增加缓存层
3. 使用explain、profile、showLog分析语句,优化查询语句
a. 使用连接查询(JOIN)来代替子查询
b. 使用联合(union)来代替手动创建的临时表
4. 使用索引
5. 分库分表
6. 读写分离
a.读写分离就是在主服务器上修改,数据会同步到从服务器,从服务器只能提供读取数据,不能写入,实现备份的同时也实现了数据库性能的优化,以及提升了服务器安全
b. 使用binlog日志进行数据同步
Mysql主从复制
1. 主服务器将操作记录到二进制日志binlog中
2. 备服务器将日志拷贝到中继日志里
3. 备服务器重新执行日志里的事件
Mysql存储引擎
使用show engines查看引擎
1. MySQL5.5之前的默认MyISAM:访问速度快,不支持事务
2. MySQL5.5之后的默认InnoDB:会占用更多的磁盘空间,支持事务
常见问题
1. 大表分页查询如何优化?
a. 区分不同的场景,如果主键是连续的,且按照主键排序的,可以filter主键id查询第一页
b. 如果order有序不连续的字段,或者主键,可以建立索引,查询在索引中的位置看第一页。这样会产生数据遗漏问题,可能需要组合查询
c. 如果根据天等类似字段查询可以考虑分表
d. 根据条件查出唯一键,如id,然后利用id作in查询
e. 考虑将数据写到es,利用es的scroll作分页
2. 如何保持Mysql和Redis数据一致性
a. 区分不同的场景,如果请求太多,可以先写到Redis,定时同步到Mysql
b. 用canal订阅Mysql的binlog,再通过MQ推送修改Redis
浙公网安备 33010602011771号