zoukankan      html  css  js  c++  java
  • 高性能MySQL第三版-第一章MySQL架构与历史

    MySQL架构最与众不同的是将查询处理及其他系统任务数据的存取/提取相分离。

    这种处理和存储分离的设计可以在使用时根据性能、特性,以及其他需求来选择数据存储的方式。

    1.1逻辑架构

    第一层:连接/线程处理。用于连接处理、授权认证、安全等。

    第二层:查询缓存、解析器、优化器。大多数核心功能都在这一层,包括查询解析、分析、优化、缓存以及所有内内置函数,所有跨存储引擎的功能(存储过程、触发器、视图)。

    第三层:存储引擎。负责数据存储和提取。服务器通过 API 与存储引擎进行通信, 这些 API 屏蔽了存储引擎之间的差异,使得这些差异对上层的查询过程透明。 存储引擎不会去解析SQL,那是第二层干的事,不同存储引擎也不会相互通信,只是简单地响应上层服务器的请求。

    问题:到底什么是存储引擎?

    假设你也想自己写一个存储引擎,你需要定义好一个表的数据用什么格式来存储,用什么样的索引来访问这些数据, 然后你需要写一个类,这个类需要实现一些约定好的接口函数(创建表、打开表、写入数据等)。

    在这些方法的实现当中,你需要处理好如何创建表,如何插入数据,如何开始事务,提交事务这些功能。

    你写的这个类会被MySQL 所装载使用,然后在合适的时候调用相关方法,于是你这个类就变成了存储引擎!

    如何写一个自定义的存储引擎

    1.1.1 连接管理与安全性

    每个客户端连接在服务器进程中都有自己的线程。连接的查询只会在该单独的线程中执行,该线程只能轮流在某个CPU核心或CPU上运行。服务器会缓存线程,因此无需为每个新连接创建和销毁线程。(MySQL 5.5 and newer versions support an API that can accept thread-pooling plugins, so a small pool of threads can service many connections.)

    客户端(应用)连接到 MySQL 服务器时,服务器需要对其进行认证(用户名、主机信息、密码或认证证书等)。

    客户端连接成功,也就是认证成功,服务器会继续验证客户端的相关权限。

    问题:每个客户端连接都会占用一个线程,那客户端没有查询发出的时候,这个线程能不能被别的客户端连接使用呢?

    读书群里提出问题讨论。问题重点在客户端没有查询发出,说的不明确,下面分几种情况来说。

    • 连接阶段顺利,用户线程进入命令阶段,而命令阶段又没有SQL指令。

    这时候就要看wait_timeoutinteractive_timeout参数是多少了,默认28800s,也就是8h。(The number of seconds the server waits for activity on an interactive connection before closing it)

    在连接没有被关闭之前,这个线程不能被其他客户端连接使用。(连接关闭有两种,一种超过MySQL的wait_timeout,一种是客户端发送一个 COM_QUIT命令断开连接)

    • 连接阶段不顺利

      那就是和这个参数有关了connect_timeout,默认10s,超过了那这个线程就可以被别的客户端连接使用。(The number of seconds that the mysqld server waits for a connect packet before responding with Bad handshake. The default value is 10 seconds.)

    MySQL连接处理和扩展

    1.1.2 优化与执行

    优化器并不关心表使用的事什么存储引擎,但存储引擎对于优化查询是有影响的。优化器请求存储引擎提供容量或者某个具体操作的开销信息。例如,某些存储引擎的索引,可能对一些特定的查询有优化。

    1.2 并发控制

    只要有多个查询需要在同一时刻修改数据,都会产生并发控制的问题。本章目的讨论 MySQL 在两个层面的并发控制:服务器层与存储引擎层。

    服务器层:锁定表(lock tables)和解锁表(unlock tables)的语句。服务器层会为诸如ALTER TABLE之类的语句使用表锁,而忽略存储引擎的锁机制。

    存储引擎层:存储引擎都可以实现自己的锁策略锁粒度,不同存储引擎实现锁机制方式不同。

    并发控制一般都会涉及到事务。MySQL服务层不管理事务,事务是有存储引擎实现的。同个事务中避免使用多种存储引擎。

    InnoDB的隐式锁定会根据隔离级别在需要的时候自动加锁。显式锁定,这些语句应该尽量避免使用:

    SELECT ... LOCK IN SHARE MODESELECT ... FOR UPDATE

    不属于SQL规范,是在存储引擎层做的并发控制。

    锁粒度

    MySQL 中提供了两种锁粒度:表级锁、行级锁。

    尽量只锁定需要修改的那部分数据,而不是所有的资源。锁定的数据量越少,发生锁争用的可能就越小,系统的并发程度就越高。

    但是加锁需要消耗资源,锁的各种操作(包括获取锁、释放锁、以及检查锁状态)都会增加系统开销。因此锁粒度越小,系统开销就越大。

    锁策略,就是在锁的开销和数据安全性之前寻求平衡,这种平衡当然也会影响性能。

    锁类型

    详细参考别人笔记:数据库系统原理-封锁

    1.读写锁

    • 互斥锁(Exclusive),简写为 X 锁,又称写锁。
    • 共享锁(Shared),简写为 S 锁,又称读锁。

    2.意向锁

    意向锁在原来的 X/S 锁之上引入了 IX/IS,IX/IS 都是表锁,用来表示一个事务想要在表中的某个数据行上加 X 锁或 S 锁。

    1.3 事务

    ACID概念、ACID之间的关系、不可重复读、幻读图解见数据库系统原理分享

    1.3.1隔离级别

    隔离性(Isolation)的细分

    • Read uncommited(未提交读)

      事务可读取未提交的数据,称为脏读。性能上不会比其他级别好太多,实际一般很少用。

    • Read commited(提交读)

      事务从开始到提交前的操作,对其他事务是不可见的。大多数据库默认是这个隔离级别。

    • Repeatable read(可重复读)

      在同一个事务中多次读取同样的数据记录结果是一致的。MySQL默认的事务隔离级别。

    • Serializable(可串行化)

      强制事务串行执行,在读取的每一行数据上都加了锁。

    image

    不可重复读。两次执行同样的查询,可能会得到不同的结果。

    幻读。A事务读取某个范围内的记录(比如x表的count),B事务又向x表新增一条数据,A事务再次读取结果和第一次不同。

    1.3.2 死锁

    两个或者多个事务在同一资源上相互作用,并请求锁定对方占用的资源,从而导致恶性循环的现象。

    死锁的产生有双重原因:1、真正的数据冲突,比较难避免。2、存储引擎的实现方式造成的。(不同存储引擎,锁的执行顺序不同。所以相同语句执行,有些存储引擎会死锁,有的不会。)

    部分或者完全回滚其中一个事务,才能打破死锁。

    1.3.3 事务日志

    预写式日志(Write-Ahead Logging),修改数据需要些两次磁盘。

    存储引擎在修改表数据时只需修改其内存拷贝,再把修改的行为持久到硬盘的事务日志中,不用每次修改数据本身持久化到硬盘上。

    事务日志持久后,内存中被修改的数据在后头可以慢慢刷回磁盘。

    1.3.4 MySQL 中的事务

    MySQL 中默认自动提交(AUTOCOMMIT)模式。如果不是显示的开启一个事务,则每个查询都被当做一个事务执行提交操作。

    修改 AUTOCOMMIT 变量对非事务型的表不会有任何影响。

    1.4 多版本并发控制

    读写不互相等待,能极大地提高数据库的并发能力。

    并发情况下数据一致性问题,刘大文章数据库村的旺财和小强 有关mvcc的例子

    产生并发不一致性问题的主要原因是破坏了事务的隔离性,解决方法是通过并发控制来保证隔离性。并发控制可以通过封锁来实现,但是封锁操作需要用户自己控制,相当复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。

    这里面也有多版本并发控制的例子数据库系统原理

  • 相关阅读:
    公用表表达式(CTE)的递归调用
    c# 如何让tooltip显示文字换行
    实战 SQL Server 2008 数据库误删除数据的恢复
    SQL SERVER数据库中 是否可以对视图进行修改删除
    asp.net中实现文件批量上传
    sql server 2008学习2 文件和文件组
    sql server 2008学习3 表组织和索引组织
    sql server 2008学习4 设计索引的建议
    sql server 2008学习10 存储过程
    .net 调用 sql server 自定义函数,并输出返回值
  • 原文地址:https://www.cnblogs.com/neilz/p/12287524.html
Copyright © 2011-2022 走看看