第一章 Mysql的架构与历史
1.读写锁:
读锁是共享的,多个线程可以同时读取同一个资源;写锁是排他的,写锁可以阻塞其他的读锁和写锁。
2.锁粒度(即行锁和表锁级别):
表锁: 当一个线程正在对一张表进行(插入、删除、更新等)前,需要先获得写锁,这会阻塞其他线程对这张表的读写操作。
行级锁: 当一个线程在对一张表的某条数据进行(插入、删除、更新等)前,需要先获得表锁写锁,和行锁写锁,这会阻塞其他线程对这行数据的读写操作。
3.事务(即一组原子性的sql语句):
3.1 ACID即(atomicity,consistency,isolation,durability):
原子性: 整个事务要不全部提交,要不全部回滚。
一致性: 事务只有commit和rollback两种情况。
隔离性: 一个事务所做的修改在最终提交以前,对其他事务是不可见的。
持久性: 一旦事务提交,则其所做的修改就会永远的保存在数据库中。
3.2 隔离级别
READ UNCOMMITTED(未提交读): 其他事务可以读到当前事务没提交的写操作。这也称为脏读(Dirty Read)。
READ COMMITTED(提交读): 其他事务不可以读到当前事务未提交的写操作。可能会出现一种情况,在一个事务中的两次相同的查询语句得到的结果集不同。提交读也称为不可重复读。
REPEATABLE READ(可重复读): 可重复读解决了脏读问题。该级别保证了在同一个事务中多次读取同样记录的结果是一致的。当时还是存在幻读现象(当事务读取一个范围内的记录时,另一个事务在这个范围插入一批新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)的现象)
SERIALIZABLE(可串行化): 它通过强制事务串行执行,避免了前面说的幻读的问题。
3.3 死锁
InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚
3.4 事务日志
事务日志可以提高事务的效率。使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到之在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到硬盘。事务日志持久后,内存中被修改的数据在后台可以慢慢地刷回到磁盘。
3.5 Mysql中的事务
自动提交(AUTOCOMMIT): 如果不是显式地开始一个事务,则每个查询都被当做一个事务执行提交操作。
修改事务的隔离级别: SET [SESSION] TRANSACTION ISOLATION LEVEL READ COMMITTED;
MyISAM为非事务性存储引擎
3.6 隐式和显式锁定
InnoDB采用的是两阶段锁定协议(two-phase locking protocol)。在事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一是个被释放。这里的锁定时隐式锁定。
显式锁定即 LOCK TABLES 语句。
4 多版本并发控制(MVCC)(只兼容READ COMMITTED ; REPEATABLE READ)
MVCC的实现,是通过保存数据在某个时间点的快照来实现的。也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对同一张表,同一时刻看到数据可能是不一样的。
InnoDB的MVVC实现是在每行有两个隐藏属性(创建版本号和删除版本号)
下面是REPEATABLE READ隔离级别下,MVCC具体是何如操作的:
SELECT
InnoDB会根据以下两个条件检查每行记录:
a. InnoDB只查找版本早于当前事务版本的数据行(也就是,行的版本号小于或等于事务的系统版本号),这样可以确保 事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过得。
b. 行的删除版本要么未定义,要么大于当前事务版本号。这可以确保事务读取到的行,在事务开始之前被删除。
INSERT
InnoDB为新插入的每一行保存当前系统版本号作为行版本号。
DELETE
InnoDB为删除的每一行保存当前系统版本号作为删除标志
UPDATE
InnoDB为插入一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统保本号到原来的行作为行删除标识。
5 mysql的存储引擎
5.1 SHOW TABLE STATUS LIKE 'user' \G
Row_format: 行的格式。对于MyISAM表,可选的值为Dynamic、Fixed或者Compressed。Dynamic的长度是可变的,一般包含可变长度的字段,如 VARCHAR 或者 BLOB。Fixed的行长度则是固定的,只包含固定长度的列,如CHAR和INTEGER。Compressed的行则只在压缩表中存在。
Rows: 表中的行数。对于MyISAM和其他一些存储引擎,该值是精确的,但对于InnoDB,该值是估计值。
5.2 InnoDB存储引擎
InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级别。其默认级别是REPEATABLE READ ,并且通过间隙(next-key locking)策略防止幻读的出现。间隙锁使得InnoDB不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻影行的插入。
InnoDB是基于聚簇索引。聚簇索引对主键查询有很高的性能。不过他的二级索引中必须包含主键列,所以主键列很大的话,其他索引都会很大。
5.3 MyISAM存储引擎
MyISAM提供大量的特性,包括全文索引、压缩、空间函数等,但MyISAM不支持事务和行级锁,
5.4 修改存储引擎 ALTER TABLE mytable ENGINE = InnoDB;
如果把一张InnoDB转化MyISAM在转会InnoDB会丢失外键。
第二章 MYSQL 基准测试
(主要测试mysql在机器的 各种压力测试)
(看了一遍感觉没多大用,略)
第三章 服务器性能剖析
1 一些概率性的东西
1.1 性能及完成一个场景所需要的时间度量 (表现在一个sql的响应时间)
2 慢查询日志 (经过别人的基准测试,慢查询日志对磁盘I/O性能影响很小)
2.1 通过show variables like "%query%" 查看慢查询的long_query_time,和慢查询日志地址
2.2 通过long_query_time 来设置mysql 多长时间算‘慢’的时间
3 show profile(性能剖析) (一般不用,代价还是有一丢丢)
3.1 show variables like "%profile%" 查看关于profile的变量
3.2 通过set profiling = 1;开启 profile
3.3 运行一次sql , 然后show profiles查看性能剖析的sql
3.4 通过 show profile for query [Query_ID] 来查看这个sql的各个部分的耗时
4 show [session][global] status (mysql 记录的所有的计数器信息,加上[session]为回话级别的计数器)
5 show processlist
第四章 Schem与数据类型优化
1.选择优化的数据类型
1.1 更小的通常更好 (TIMESAMP 比 DATETIME 小一半,但是不支持时区)
2.2 简单就好 (例如:用MYSQL内键的类型而不是字符串来存储日期类型,整型存储ip)
2.3 避免使用NULL
NULL使得索引、索引统计、值比较 等都更为复杂
NULL列会使用更多的存储空间
NULL列被索引时,每个索引记录需要一个额外的字节