HOME/Articles/

mysql相关记录-概述部分

Article Outline

mysql相关记录-概述部分

一、mysql服务器分层

mysql服务器大致可以分为三层:

第一层:

连接处理,授权认证,安全认证等

第二层:

mysql的大多数核心服务功能都在这一层,包括查询解析、分析,优化、缓存以及所有的内置函数(日期函数,时间函数等)以及所有跨存储引擎的功能(存储过程,触发器,视图等)

第三层:

存储引擎,负责MySQL中的数据存储和提取,不同的存储引擎,对上层提供相同的API接口,来屏蔽不同存储引擎之间的差异。

二、SQL语句执行:

对于一个select语句,在解析查询之前,服务器会先检查查询缓存,如果能够在其中找到对应的查询(通过计算sql语句的hash值进行比较,所以,即使相同的sql语句,也会因为关键字的大小写不同,使得计算出的hash值不同,因而无法找到对应的缓存数据),如果能够在其中找到对应的查询,服务器就不必再执行查询解析;否则,则进行解析sql语句,优化,和执行查找数据。

三、并发控制

一般并发的问题,是通过两种锁来解决的,这两种锁称为共享锁(读锁)和排他锁(写锁),读锁是共享的,多个客户可以在同一时刻同时读取同一资源,互不干扰。写锁时排他的,写锁会阻塞其他的写锁和读锁。

1、锁的粒度

一般锁分为两种粒度,表锁和行级锁

表锁是开销最小的锁策略,会锁定整张表。

行级锁:行级锁可以最大程度地支持并发处理,同时也带来了最大的锁开销。

四、事务:

事务是一组原子性的SQL查询或者一个独立的工作单元,事务内的语句,要么全部执行成功,要么全部执行失败。

ACID:原子性,一致性,隔离性,持久性

1、隔离级别:

较低级别的隔离通常可以执行更高的并发,系统的开销也更低。

(1)、未提交读(READ UNCOMMITED)

事务中的修改,即使没有提交,对于其他事务也都是可见的,事务可以读取未提交的数据,称之为脏读,这个级别会导致很多问题,而且性能没有很高,一般很少使用。

(2)、提交读(READ COMMITED)

大多数的数据库都是提交读的隔离级别(MYSQL不是),一个事务开始时,只能看见已经提交的事务所做的修改,换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的,这个级别有时候也叫不可重复读,因为两次执行相同的查询,可能会得到不一样的结果;

其实一开始并不太理解不可重复读的意思,仔细想想,其实就是 A事务在做更新操作,此时,A还没有提交,这时候,B事务做查询操作,查询不到A事务做出的更新;A提交了更新事务,而B事务(注意是同一个事务,上一个查询的也是B),这次查询,会查到A事务做出的修改,即两次查询会得到不一样的结果;

(3)、可重复读(REPEATABLE READ)

该级别保证了同一事务中多次读取同样记录的结果是一致的。可重复读是mysql的默认事务隔离级别。

可重复读理论上不能解决幻行的问题,即某个事务读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,之前的事务再次读取时,会读取到这个新增的行

MySQL的InnoDB引擎,通过多版本并发控制MVCC解决了幻行的问题。

(4)、可串行化(SERIALIZABLE)

它通过强制事务串行执行,避免了幻读,简单来说,可串行化是在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用问题,实际应用中很少用到这个隔离级别,只有在非常需要保证数据一致性,并且可以接受没有并发的情况下,才考虑该级别。

五、多版本并发控制

MySQL的大多数事务型存储引擎都不是简单的行级锁,而是实现了多版本并发控制。

MVCC的实现,是通过保存数据在某个时间点的快照来实现的。也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。

InnoDB的MVCC是通过在每行记录后边保存两个隐藏的列表实现的,这两个列,保存了创建时间和行的过期时间,并不是真的保存时间,而是系统版本号,每开始一个新的事务,系统版本号就自动加一,通过版本号,就可以保证数据的一致性。

SELECT :

只查询版本早于等于当前的数据行,这样可以保证事务要么是开始查询时已经存在的,要么是事务自身操作修改的。

行的删除版本要么未定义,要么大于当前事务的版本号,这可以确保事务读取到的行,在事务开始之前未被删除。

INSERT、UPDATE、DELETE:

InnoDB为新插入的每一行保存当前的系统版本号作为行版本号。

保存这两个额外的系统版本号,使得大多数读操作都可以不用加锁。