高性能mysql读书笔记一
一.Mysql的架构和基本特性
1.基本的分为mysql服务器和存储引擎,mysql服务器处理连接管理,查询缓存,查询分析,查询优化,存储引擎处理具体的查询,目前而且,事务也是在存储引擎中实现的,这也就意味做如果事务跨越不同存储引擎的表,并不可靠。
2.锁
明白并行和排队的区别,并行是running状态,指任务已经在运行(对于单核,可能要等待调度,考虑核数如果等于任务数,所有的任务都在运行),排队的话,任务还有开始运行,任务等待自己的状态变为running.读锁会排斥所有的写锁,而写锁会排斥所有的锁。这一有一个东西很微妙,当前有running的读锁的时候,写锁不能执行,但是写锁如果在队列里往往会被提前到队列第一个,这是因为,这样可能让之后的所有读都并发执行,更大量的并发带来更高的效率。
3.锁粒度, 分为表锁和行锁
4.事务
ACID测试,原子性Atomicity,一致性Consistency,隔离性(Isolation),持久性(durability)
隔离性又分四级
(1).Read UNcommited即未提交内容对其他事务可见。这个基本上不满足原子性,和一致性,隔离性。
(2).read committed只能看到其他事务提交的数据,但这个有个问题是不可重复读,在一个事务A中,读取内容Z,事务B修改内容Z并提交,A再读取内容Z,内容已经变化,但理想情况是,事务开始后只要自己没有修改数据,看到的数据都应该是一样的。实现:只需要在事务提交的时候再释放该事务类的所有写锁。
(3).repeatable read这个解决了上一级的问题,简单的实现的话,就是读锁也到事务提交的时候再释放,这样的问题是一个事务中要占有太多的锁,占有的时间也变长(不是原子的一条语句)这样引起并发问题,并容易造成死锁。解决方法是MVCC(多版本并发控制),每个事务开始的时候会自增一个版本号,每一行记录会记录该行的create时的版本号和delete时的版本号,同一行可能有多个版本。该技术很牛逼啊,不仅解决了前面那个戳办法锁过度的问题,而且在执行读取的时候,根本就不用加锁了,即写不用等待读完成了,但是读需要等待写完成,而且在这样的实现办法下,写锁也不需要等到事务完成再释放,写完就可以释放,而且还不会出现“幻影”行,该隔离级不亏为innoDB的默认隔离级。MVCC的优势在于并发性能非常好,本质上就是冗余了历史的行给其他并发的事务去读,冗余历史行会增加其他开销的清理管理开销,如果其他并发的事实数量比较小,比如1个,这个增加的开销“可能”就不值得了。
(4).串行化,这个应该就是不让事务并行执行,当然也就没有问题了。
5.死锁,死锁就是自己拥有了锁又去请求别的锁,而别人占有了自己要请求的锁,同时又请求自己占有的锁,死锁只会发生在事务中,原子操作不会引发,因为不会有占有->请求两步。死锁不是什么大问题,只要能检查到死锁,再回滚一个事务就可以了,一般事务都用的比较少,死锁发生的机会应该更小,这个一般不会构成性能问题。
6.预写式日志。innodb有自己的内存数据缓存(跟mysql服务器层的查询缓存不是一回事,该缓存最大不会超过数据库的大小,这个我们的应用会比较小应该不会超过5G),写入的时候可以先写入内存。在写入事务日志,这个是顺序IO比修改数据的随机IO要快不少,同时innodb_flush_log_at_trx_commit,该写入动作不跟事务同步,而是每秒执行一次,进一步提高性能。