事务、隔离性
数据库事务四大特性:原子性(Atomicity)、隔离性(Isolation)、持久性(durability)、一致性(consistency)
原子性
指事务中的操作必须像原子一样,不可分割,要么全部成功,要么全部失败,可以通过undolog来实现。
隔离性
指多个事务在执行时相互隔离,在事务并发执行时,有三种场景:读与读、读与写、写与写,此时可能出现四种问题:
丢失更新(Last To Modify)
事务A执行了更新操作,但未提交,事务B也执行了更新操作,也未提交,接着事务A执行提交,事务B执行提交,此时,事务A的更新会被事务B的更新所覆盖掉,发生丢失更新
脏读(Dirty Read)
事务B执行了更新操作,而事务A读取到了未提交的数据,而未提交的数据存在两种结果:1.被提交 2.被回滚,当事务B执行了回滚操作,事务A读取到的数据即脏数据,行为被称为脏读
不可重复读(Unrepeatable Read)
当事务A进行了两次读取操作,而在这两次读取操作之间,另一个事务B对数据进行了修改,从而导致事务A两次读取到的数据不一致,出现不可重复读
幻读(Phantom Read)
例如事务A对表中所有数据进行了修改,而事务B在之后插入数据,接着事务A进行读取数据,发现存在有未修改的数据,就好像产生了幻觉一样,因此被称为幻读
为了避免以上情况的发生,SQL提供了四种事务隔离级别:
读未提交(Read Uncommitted)
一个事务还未提交,所做的操作是可以被其它事务读取到的,丢失更新的解决是数据库层面上的,所以读未提交可以解决丢失更新
读已提交(Read committed)
一个事务所做的操作必须等提交之后才能被别的事务所读取到,即未提交的操作是不可见的,读已提交可以解决丢失更新、脏读问题
可重复读(Repeatable Read)
一个事务在其执行的期间所读取到的数据都是一致的(除了自身修改),读已提交可以解决丢失更新、脏读、不可重复读,该隔离模式为MySQL的默认模式
可串行化(Serializable)
可串行化为事务隔离级别最高的,同时也是并发性能最低的,所有的操作都会进行加锁,当出现锁冲突时,只能等待
丢失更新 | 脏读 | 不可重复读 | 幻读 | |
---|---|---|---|---|
读未提交 | ✅ | ❌ | ❌ | ❌ |
读已提交 | ✅ | ✅ | ❌ | ❌ |
可重复读 | ✅ | ✅ | ✅ | ❌ |
可串行化 | ✅ | ✅ | ✅ | ✅ |
持久性
指事务一旦提交或回滚,数据的改变是永久的,通过redo log实现。
一致性
事务完成时,数据必须符合预期结果,当实现原子性、隔离性、持久性,一致性就能够实现。
索引
索引的作用是改善数据库表查询速度的一种数据结构,可以指定一个列或者多个列来创建索引,MySQL索引是在存储引擎层实现的。索引的结构有多种,最常见的是以B+Tree为结构,MySQL的默认引擎InnoDB、MyISAM、Memory都支持,另外还有Hash结构,底层由hash table实现,但这种结构不支持范围查询,Memory引擎支持改结构,以及MyISAM支持的主要用于索引多维信息的R-tree结构和通过倒排索引实现的全文索引。
索引可以分为主键索引、唯一索引、常规索引、全文索引,其中主键索引只有一个。
MySQL的InnoDB引擎的索引可以分为聚集索引(Clustered Index)和二级索引(Secondary index),二级索引又可以称为非聚集索引和辅助索引。聚集索引中键值的逻辑顺序决定了数据的物理顺序,而物理顺序只有一种情况,因此聚集索引有且仅有一个,数据与索引放到一起,叶子结点保存了行数据。如果存在主键,主键索引就是聚集索引,如果不存在主键,则选取第一个unique索引作为聚集索引,否则InnoDB默认选择或者添加一个隐藏列作为主键索引。
索引的设计原则
1.针对数据量较大,查询比较频繁的表建立索引。
2.针对常作为条件操作的字段建立索引
3.尽量建立唯一索引,区分度越高,索引的效率越高
4.如果是长字符串,可以建立前缀索引
5.尽量使用联合索引,联合索引很多时候可以覆盖索引,避免会变查询
6.控制索引的数量,索引越多,维护的成本就越大
SQL性能分析
为什么需要性能分析?如果希望对数据库进行优化,必须知道可以优化的地方,可以从以下三个方面进行:慢查询日志、Profile、Explain。
慢查询日志
慢查询日志记录了MySQL中响应时间超过阀值long_query_time的sql语句,该阀值的默认值为10,即运行时间超过10秒的sql语句将被记录到慢查询日志。慢查询日志默认不开启,我们可以查看慢查询日志是否开启
show variables like 'slow_query_log'
通过my.cnf文件可以开启慢查询,也可以选择临时启用
set global slow_query_log = 1
更改阀值时间
set global long_query_time = second
具体的信息可以通过slow_query.log文件查看
Profile
Profile可以分析sql语句执行的系统资源消耗情况,可以通过Profile查看sql语句的执行时间、CPU开销、块IO开销等信息,Profile默认是不开启的。
开启profiling
set profiling = 1
查看profiling
show profiling
通过指定query_id来查看sql语句的具体情况
show profile for query id
Explain
Explain可以用来分析sql查询语句的执行计划,在查询语句前面添加explain即可。
其返回信息字段为:
字段 |
---|
id |
select_type |
table |
partitions |
type |
possible_keys |
key |
key_len |
ref |
rows |
filtered |
extra |