zoukankan      html  css  js  c++  java
  • 《高性能MySQL》- 01 MySQL架构与历史

    MySQL 逻辑架构

    最上层的服务并不是MySQL所独有的,大多数基于网络的客户端/服务器的工具或者服务都有类似的架构

    第二层是MySQL的核心服务功能所在的一层,包括一些查询解析,分析,优化,缓存以及所有的内置函数

    第三层包含了存储引擎。存储引擎复制MySQL中数据的存储和提取

    连接管理与安全性

    每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中执行,该线程只能只能轮流在某个CPU核心或者CPU中运行。服务器会负责缓存线程,因此不需要为每个新建的连接去创建或者销毁线程

    优化与执行

    MySQL会解析查询,并创建内部数据结构(解析树),然后对其进行各种优化,包括重写查询,决定表的顺序,以及选择合适的索引等。用户也可以通过关键字提示(hint)优化器,影响它的决策过程

    优化器并不关心表使用的是什么存储引擎,但不同的存储引擎对于优化查询是有影响的

    对于select语句,查解析器之前会先查缓存,如果找不到才会去执行解析优化这个过程。

    并发控制

    不论何时,只要有多个查询需要在同一时刻需改数据,都会产生并发控制的问题。其实不难想象,总会有同一时间可能产生多个用户操作同一数据库的情况。

    读写锁

    在处理并发或写时,可以通过实现一个由两种类型的锁组成的锁系统来解决问题。这两种类型的锁通常被称为共享锁和排他锁,也叫读锁和写锁。

    写锁,再写的时候加锁,不能进行读,读锁在读的时候加锁,可以其他用户读,但不能写

    锁粒度

    一种提高共享资源的并发性的方式就是让锁定对象更有选择性

    表锁

    表锁是MySQL中最基本的锁策略,它在用户操作时会锁住整张表。一个用户在对表进行写操作前,需要先获得写锁,这会阻塞其他用户对该表的所有读写操作。通俗一点说,当某个用户操作这个表时,其他用户不能操作这张表,但是可以操作其他表。

    行锁

    行锁可以最大程度上支持并发处理(同时也带来了最大的锁开销)。行级锁只在存储引擎层实现,而MySQL服务层没有实现。服务器层完全不了解存储引擎中的锁实现。

    事务

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

    原子性(atomiccity):一个事务必须被视为一个不可分割的最小工作单元,整个事务中要么全执行,要么全不执行

    一致性(consistency):数据库总是从一个一致性的状态转换到另一个一致性状态

    隔离性(isolation):通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的

    持久性(durability):一旦事务提交,则其所做的修改就会永久保存到数据库中

    隔离级别:

    READ UNCOMMITTED(未提交读):在READ UNCOMMITTED 级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,也被称为脏读。

    READ COMMITTED(提交读):一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候也叫做不可重复读。

    REPEATABLE READ(可重复读):MySQL的默认级别,但是无法解决幻读问题。所谓的幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。但是InnoDB和XtraDB存储引擎通过MVCC解决了这个问题

    SERIALIZANLE(可串行化):强制事务串行。效率差,谨慎使用

    MYSQL默认的隔离级别是可重复读,当然这个也可以自己设置。

    死锁

    死锁是指两个或者多个事务在同一资源上互相占用,并请求锁定对方的资源,从而导致恶性循环的现象。其实理解起来也不难,这里的死锁和OS里的死锁原理其实是一样的

    为了解决死锁的问题,数据库系统实现了各种死锁检测和死锁超时机制。越复杂的系统,比如InnoDB存储引擎,越能检测到死锁的循环依赖,并立即返回一个错误。InnoDB目前的处理方法是,将持有最少行级排他锁的事务进行回滚

    锁的行为和顺序是和存储引擎相关的。以同样的顺序执行语句,有些存储引擎会产生死锁,有些则不会。死锁的产生有些是真正的数据冲突产生的,这种情况是很难避免的,但有些则完全是由存储引擎的实现方式导致的

    事务日志

    简单来说,使用日志是在修改表的时候先不持久到磁盘,而是修改内存拷贝,在日志追加。这样可以提高查询效率,而且事务日志是采用追加的方式,持久化的时候,一个可以慢慢回刷,而是顺序刷新,不是随机。当然这里不难想象,如果系统挂了,内存的东西就消失了,这时候就要靠日志来做修复了

    MySQL中的事务

    MySQL默认采用自动提交的概念(AUTOCOMMIT)模式,也就是说,如果不是显示地开始一个事务,则每个查询都会被当做一个事务提交。这个开关是自由选择的,也可以关闭这个,关闭的话,直到显示执行COMMIT或者ROLLBACK时,事务才会结束。当然对于非事务型表,这个操作是没意义的。

    在事务中混合使用存储引擎,事务是由下层的存储引擎实现的,所以在同一个事务中,使用多种存储引擎是不可靠的。但是混合使用事务型表和非事务型表是可以的。如果非特殊情况,不建议混合使用

    隐式和显式锁定

    事务在执行过程中,随时都可以锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一时刻被释放,这都是隐式的。当然InnoDB也支持显示的锁的方式

    多版本并发控制

    就是我们通常所说的MVCC,MVCC虽然实现机制各不相同,但大部分都实现了非阻塞的读操作,写操作也只锁定必要的行。MVCC的实现,是通过保存数据在某个时间点的快照来实现的。也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对于同一张表,同一时间看到的数据可能不同。这个有点绕,举个例子说明一下:A事务是在00:00执行的,这个时候数据库有个快照a,它读取的是快照a。一分钟后,A事务还没执行完(只是单纯的举例子)00:01时,B事务开始执行了,这个时候B开始执行,它读到的快照b,a和b可能是不同,这个你要理解。然后00:02的时候,AB同时读这个表里的一行数据,确实可能不同,因为没法保证a和b是一样的。

    InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存的是过期时间。当然存储的并不是实际的时间值而是系统版本号。每开始一个事务。系统版本号都会自动递增。保存这两个版本号,使得大多是操作都可以不用加锁。这样设计使得读数据操作很简单,性能很好。不足之处是每行记录都需要额外的空间,需要做更多的行检查工作,以及一些额外的维护工作。

    MySQL的存储引擎

    这里我不多赘述了,以后会在另一个《InnoDB实战》笔记里去详述

    具体怎么选择存储引擎,原则就是,除非用到某些特性,否则优先使用InnoDB。具体情况得具体分析,这个我也没法给你去具体描述,因为我遇过的情况太少了。而且,实不相瞒,我只用过InnoDB,其他都是理论了解。

  • 相关阅读:
    IntelliJ IDEA AndroidStudio SVN无法使用
    三极管封装
    STC等单片机一开机就停电模式烧写程序办法
    CC2541设置中断输入模式
    C# WinForm 多线程 应用程序退出的方法 结束子线程
    CorelDrawX8安装时提示已安装另一个版本
    Win10下Prolific USB-to-Serial Comm Port驱动提示不能使用
    Keil5创建GPIO
    SQL行列转置
    Excel复制粘贴假死
  • 原文地址:https://www.cnblogs.com/Moriarty-cx/p/11882773.html
Copyright © 2011-2022 走看看