- 数据库事务ACID(原子性、一致性、隔离性、持久性)
原子性:事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生,DBMS默认一条sql即为一个事务,自动提交
一致性:事务开始之前和结束之后,数据库的完整性约束未被破坏,即关系数据的完整性和业务逻辑一致性不可破坏
隔离性:多个事务并发访问时,事务之间是隔离的,一个事务不影响其他事务的运行效果
这指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
- 事务之间的相互影响:脏读,不可重复读,幻读,丢失更新
脏读:一个事务读取了另外一个事务未提交的数据,这个数据有可能回滚
不可重复读:一个事务范围内两个相同的查询却返回了不同数据,这是由于查询时系统中其他事务修改的提交而引起的
幻读:一个事务对表中数据做全量修改,同时另一个事务也修改表中的数据(向表中插入数据),第一个事务发现执行修改之后任然存在没有修改的数据
丢失更新:两个事务同时读取同一条记录,A先修改记录,B也修改记录(B是不知道A修改过),B提交数据后B的修改结果覆盖了A的修改结果
持久性:事务完成之后,事务对数据库做的更改持久地保存在数据库中,不会被回滚
- MySQL事务隔离级别
读未提交(Read Uncommitted):所有事务都可以看到其他事务未提交的执行结果
读已提交(Read Committed):一个事务只能看到已提交事务的执行结果
可重复读(Repeatable Read):MySQL的默认事务隔离级别,可确保同一事务的多个实例在并发读取数据时候,会看到同样的数据行,理论上会导致幻读,InnoDB和Falcon存储引擎通过多版本并发控制机制解决了该问题
可串行化(Serializable):最高隔离级别,强制事务排序,解决幻读问题,在每个读的数据行上面添加共享锁,这种情况会导致大量超时和锁竞争
- MySQL索引:在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构
索引类别(B+树索引、全文索引、哈希索引),索引的原理
B+树索引:B+树性质
建立索引的原则
最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配
索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)
尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可
选择区分度高的列作为索引,区分度的公式是count(distinctcol)/count(*),表示字段不重复的比例,比例越大扫描记录数越少
=和in可以乱序,比如a = 1 and b = 2and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式
- 常见索引:
主键索引:特殊的唯一索引,不允许有空值
唯一索引:索引列值必须唯一,但允许有空值
普通索引
全文索引:支持各种字符在内的搜索,也支持自然语言搜索和布尔搜索
组合索引
- 优化:limit 20000 加载很慢原因,解决方式
原因:数据库表过于庞大,LIMIT offset, length中的offset值过大,则SQL查询语句会非常缓慢,你需增加order by,并且order by字段需要建立索引
解决方式:
子查询优化:
在子查询里先从索引获取到较大id,然后倒序排,再取10行结果集
select id,title from collect where id >= (select id from collect order by id limit 90000,1) limit 10;
偏移1000以上使用子查询法
id 限定优化
假设数据表的id是连续递增,根据查询的页数和查询的记录数可以算出查询的id的范围,使用 id between and 来查询
select * from orders_history where type=2 and id between 1000000 and 1000100 limit 100;
select * from orders_history where id >= 1000001 limit 100;
倒排表优化:
类似建立索引,用一张表来维护页数,然后通过高效的连接得到数据
只适合数据数固定的情况,数据不能删除,维护页表困难
limit限制优化:
把limit偏移量限制低于某个数,超过这个数等于没数据
表连接(复合索引)优化:
通过索引构造一个小表,然后同数据进行关联,在索引中只取想要的ID所以这个会非常快,把取出来的很少的ID再同数据表关系,这样能大大提高查询效率
- 锁
乐观锁:假设不会发生并发冲突,在数据进行提交更新操作时检查是否违反数据完整性,不能解决脏读的问题。
数据版本(Version)记录机制:乐观锁最常用的实现方式,即为数据增加一个版本标识(或者时间戳“timestamp”),通过为数据库表增加一个数字类型的“version”字段来实现。读取数据时,将version字段的值一同读出,数据每更新一次,对version值加一。当提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作
共享锁(lock in share mode):共享锁指的就是对于多个不同的事务,对同一个资源共享同一个锁。相当于对于同一把门,它拥有多个钥匙一样。
排他锁: