已停更,转移至有道云笔记
Mysql 优化之explain你的select ,show profile, 慢查询
explain select * from answer where question_id in(4007,4008,4009) and score>0;
其中questionId有索引而 score没有
1) select_type表示的是简单的select语句。
2) type ALL表示全表扫描。
3) possible_keys 表示有可能是用了缓存。
索引分类
1)从数据结构来说B树,B+ 树
2)从物理结构来说 聚集索引(一张表只有一个),费聚集索引(字典里面以偏旁部首查询时)
3)从逻辑结构来说 主键索引:主键索引是一种特殊的唯一索引,不允许有空值 单列索引 多列索引 唯一索引或者非唯一索引(普通索引) 唯一索引:它通过确保表中没有两个数据行具有完全相同的键值来帮助维护数据完整性 直接索引 间接索引
索引的优点:通过创建唯一索引,可以保证数据库表中每行数据的唯一性,可以加快数据的查询速度,通过使用索引,可以在查询中使用优化隐藏器,提高系统的性能。
缺点:创建索引和维护索引要耗费时间,并且随着数据量的增加耗费时间也增加.索引需要占空间内存,在对表中数据进行增加,删除和修改的时候,索引也需要动态维护,这样降低了数据维护速度.
事务的隔离级别
1)未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据 会导致脏读,不可重复读,幻读
数据库一般都不会用,而且任何操作都不会加锁.
2)提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读) 会导致不可重复读,幻读
teacher_id是有索引的,如果没有的话,就是说如果一个条件无法通过索引快速过滤,存储引擎层面就会将所有记录加锁后返回,再由MySQL Server层进行过滤。但是发现不满足之后.会调用unlock_row方法,把不满足条件的记录释放锁 (违背了二段锁协议的约束)。这样做,保证了最后只会持有满足条件记录上的锁,但是每条记录的加锁操作还是不能省略的。可见即使是MySQL,为了效率也是会违反规范的
3)可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
一个数据量很大的表做批量修改的时候,如果无法使用相应的索引,MySQL Server过滤数据的的时候特别慢,就会出现虽然没有修改某些行的数据,但是它们还是被锁住了的现象。一个个锁,再分别解锁
SELECT时,读取创建版本号<=当前事务版本号,删除版本号为空或>当前事务版本号。 没加锁,通过版本号执行的
INSERT时,保存当前事务版本号为行的创建版本号
DELETE时,保存当前事务版本号为行的删除版本号
UPDATE时,插入一条新纪录,保存当前事务版本号为行创建版本号,同时保存当前事务版本号到原来删除的行
这样做业务上来说并不是最新的数据,有些业务需要最新的数据:
在每个读的数据行上都加了共享锁,可能导致大量的超时和锁竞争. 给个客户加锁.
4)串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞 所有操作都要串行运行
不可重复读:是指在一个事务内,多次读同一数据 每次读取的数值不一样,因为第一次读跟第二次读之间可能有别的事务更改了。
幻读: 注意id为1是一班
悲观锁 读也加锁,其他也加锁
乐观锁 如上锁述
数据库锁机制
- 表级锁:粒度大 由于表级锁一次会将整个表锁定,所以可以很好的避免困扰我们的死锁问题 表级锁分为读锁和写锁
- 页级锁定:会发生死锁 粒度介于
- 行级锁定 最容易发生死锁,粒度最小 InnoDB的行级锁同样分为两种,共享锁和排他锁
sql注入
就是通过把SQL命令插入到Web 表单 提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令
数据库三大范式
1)1NF是指数据库中表的每一列都是不可分割的基本数据项,同一列的数据不能有多个值。
2)第二范式就是非主属性不能部分依赖于主关键字。
3)3NF是 消除传递依赖(每一列数据都和主键直接相关,而不能间接相关)
4)BCNF表属性不能依赖其他表中非主键的属性。 以上几种都要符合更上层的
事务ACID
原子性:指整个数据库事务是不可分割的工作单位。只有使据库中所有的操作执行成功,才算整个事务成功;
一致性:指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。比如转账
隔离性:指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
持久性:指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。
数据库分页查询
select * from table WHERE … LIMIT 10,20; #返回第10-20行数据
数据库连接池原理
传统的数据库连接方式是,用户每次请求都要向数据库获取连接,而数据库连接的创建和关闭需要一定的开销。频繁的建立、关闭数据库,会极大的降低系统的性能,增大系统的开销,甚至成为系统的瓶颈。
数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。现在很多Web服务器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的实现,即连接池的实现
Spring事务
声明式事务有两种方式,一种是在配置文件(xml)中做相关的事务规则声明,另一种是基于@Transactional 注解的方式。
@Transactional(rollbackFor = Exception.class) 就这么一句话 对应resource资源
@Transactional 注解
propagation 事务的传播行为,默认值为 REQUIRED。
isolation 事务的隔离度,默认值采用 DEFAULT。
timeout 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
read-only 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true
rollback-for 用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。
no-rollback- for 抛出 no-rollback-for 指定的异常类型,不回滚事务。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。@Transactional 只能应用到 public 方法才有效,使用 AspectJ 取代 Spring AOP 代理。可以解决这个问题。