第一章
1.1
1.1.1 连接管理
这段话描述的是一种常见的服务器处理客户端连接的模型,也就是每个客户端连接对应一个服务器线程的模型。这里的“线程”是操作系统中的一个基本概念,它是CPU调度和分派的基本单位。一个线程可以理解为一个程序内部的一条执行路径,每个线程都有自己的一套独立的寄存器(如程序计数器,堆栈指针,通用寄存器等),但同属一个进程的多个线程会共享该进程的资源,如内存空间等。
在这个模型中,每当一个客户端连接到服务器时,服务器会为这个连接分配一个线程。这个线程的任务就是处理这个连接的所有请求,比如读取客户端发送的数据,处理这些数据,然后将结果发送回客户端。这个线程在执行过程中,会在服务器的CPU核心之间进行切换,也就是所谓的“轮流在某个CPU核心或者CPU中运行”。
服务器为了提高效率,通常会采用线程池的方式来管理这些线程。也就是预先创建一定数量的线程,形成一个线程池。当新的连接到来时,就从线程池中取出一个线程来处理这个连接。当连接处理完毕后,这个线程不会被销毁,而是返回到线程池中,等待处理下一个连接。这样就避免了频繁创建和销毁线程的开销,提高了服务器的处理效率。这就是这段话中“服务器会负责缓存线程,因此不需要为每一个新建的连接创建或者销毁线程”的意思。
1.1.2 优化与执行
解析查询:MySQL首先会解析查询请求,创建出对应的内部数据结构,通常是一种叫做解析树的结构。这个结构会详细描述查询的各个部分和它们的关系。
优化查询:解析完成后,MySQL的优化器会对解析树进行优化,包括重写查询,决定表的读取顺序,选择合适的索引等。用户可以通过提供特定的关键字提示(hint)来影响优化器的决策过程。同时,用户也可以请求优化器解释(explain)其优化过程的各个因素,以便了解MySQL是如何进行优化决策的。
存储引擎的影响:虽然优化器不关心表使用的是什么存储引擎,但存储引擎的特性会影响到查询优化的结果。优化器会请求存储引擎提供一些信息,如表的数据统计信息,某个具体操作的开销信息等,这些信息会被用于查询优化。
查询缓存:在解析查询之前,MySQL会先检查查询缓存。如果查询缓存中已经有了这个查询的结果,那么MySQL就不需要再进行查询解析、优化和执行的过程,而是直接返回查询缓存中的结果集。
1.2 并发控制
1.2.1
在处理并发读或者写时,可以通过实现一个由两种类型的锁组成的锁系统来解决 问题。这两种类型的锁通常被称为共享锁(shared lock)和排他锁 (exclusive lock),也叫读锁(read lock)和写锁(write lock)。
1.2.2 锁粒度
表锁:表锁是MySQL中最基本的锁策略,它的开销最小。当一个用户需要对表进行写操作(如插入、删除、更新等)时,需要先获取写锁,这会阻塞其他用户对该表的所有读写操作。只有当没有写锁时,其他读取的用户才能获取读锁,读锁之间是不互相阻塞的。在某些情况下,表锁可能有良好的性能,例如,READ LOCAL表锁支持某些类型的并发写操作。另外,写锁比读锁有更高的优先级,因此一个写锁请求可能会被插入到读锁队列的前面。
行级锁:行级锁可以最大程度地支持并发处理,但同时也带来了最大的锁开销。行级锁只在存储引擎层实现,而MySQL服务器层并不了解存储引擎中的锁实现。在InnoDB和XtraDB等存储引擎中实现了行级锁。尽管存储引擎可以管理自己的锁,MySQL本身还是会使用各种有效的表锁来实现不同的目的,例如,服务器会为ALTER TABLE等语句使用表锁,而忽略存储引擎的锁机制。