Linux运维学习:中级进阶(7)——MySQL运行原理及进阶实战

MySQL运行原理与基础架构

MySQL 基础

MySQL 是一个开放源代码的关系数据库管理系统。
原开发者为瑞典的 MySQL AB 公司,最早是在 2001 年 MySQL3.23 进入到管理员的视野并在之后获得广泛的应用。 2008 年 MySQL 公司被 Sun 公司收购并发布了首个收购之后的版本 MySQL5.1 ,该版本引入分区、基于行复制以及plugin API 。移除了原有的 BerkeyDB 引擎,同时, Oracle 收购 InnoDB Oy 发布了 InnoDB plugin,这后来发展成为著名的 InnoDB 引擎。 2010 年 Oracle 收购 Sun 公司,这也使得 MySQL 归入 Oracle 门下,之后 Oracle 发布了收购以后的首个版本 5.5 ,该版本主要改善集中在性能、扩展性、复制、分区以及对 windows 的支持。目前版本已发展到8.0+。
和其它数据库相比, MySQL 有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。

MySQL整体逻辑架构

mysql 数据库的逻辑架构如下图:
Linux运维学习:中级进阶(7)——MySQL运行原理及进阶实战_第1张图片
第一层,即最上一层:
所包含的服务并不是MySQL所独有的技术。它们都是服务于C/S程序或者是这些程序所需要的 :连接处理,身份验证,安全性等等。

第二层值得关注:
这是MySQL的核心部分。通常叫做 SQL Layer。在 MySQL据库系统处理底层数据之前的所有工作都是在这一层完成的,包括权限判断, sql解析,行计划优化, query cache 的处理以及所有内置的函数(如日期,时间,数学运算,加密)等等。各个存储引擎提供的功能都集中在这一层,如存储过程,触发器,视 图等。

第三层包括了存储引擎:
通常叫做StorEngine Layer ,也就是底层数据存取操作实现部分,由多种存储引擎共同组成。它们负责存储和获取所有存储在MySQL中的数据。就像Linux众多的文件系统 一样。每个存储引擎都有自己的优点和缺陷。服务器是通过存储引擎API来与它们交互的。这个接口隐藏 了各个存储引擎不同的地方。对于查询层尽可能的透明。这个API包含了很多底层的操作。如开始一个事 物,或者取出有特定主键的行。存储引擎不能解析SQL,互相之间也不能通信。仅仅是简单的响应服务器 的请求。

连接管理和安全

在服务器内部,每个client连接都有自己的线程。这个连接的查询都在一个单独的线程中执行。这些线程轮流运行在某一个CPU内核(多核CPU)或者CPU中。服务器缓存了线程,因此不需要为每个client连接单独创建和销毁线程 。
当clients(也就是应用程序)连接到了MySQL服务器。服务器需要对它进行认证(Authenticate)。认证是基于用户名,主机,以及密码。对于使用了SSL(安全套接字层)的连接,还使用了X.509证书。clients一连接上,服务器就验证它的权限 (如是否允许客户端可以查询world数据库下的Country表的数据)。

优化和执行

MySQL会解析查询,并创建了一个内部数据结构(解析树)。然后对其进行各种优化。这些优化包括了,查询语句的重写,读表的顺序,索引的选择等等。用户可以通过查询语句的关键词传递给优化器以便提示使用哪种优化方式,这样即影响了优化器的优化方式。另外,用户也可以请求服务器给出优化过程的各种说明,以获知服务器的优化策略,为用户提供了参数基准,以便用户可以重写查询,架构和修改相关服务器配置,便于mysql更高效的运行。
优化器并是不关心表使用了哪种存储引擎,但是存储引擎对服务器优化查询的方式是有影响的。优化器需要知道存储引擎的一些特性:具体操作的性能和开销方面的信息,以及表内数据的统计信息。例如,存储引擎支持哪些索引类型,这对于查询是非常有用的。
在解析查询之前,要查询缓存,这个缓存只能保存查询信息以及结果数据。如果请求一个查询在缓存 中存在,就不需要解析,优化和执行查询了。直接返回缓存中所存放的这个查询的结果。

MySQL逻辑模块组成

虽然从上图1看起来 MySQL 架构非常的简单,就是简单的两部分而已,但实际上每一层 中都含有各自的很多小模块,尤其是第二层 SQL Layer ,结构相当复杂的。下面我们就分别 针对 SQL Layer 和 Storage Engine Layer 做一个简单的分析。我们看下图体系结构:Linux运维学习:中级进阶(7)——MySQL运行原理及进阶实战_第2张图片

1.Connectors

指的是不同语言中与SQL的交互。

2.Management Serveices & Utilities

系统管理和控制工具。

3.Connection Pool: 连接池

管理缓冲用户连接,线程处理等需要缓存的需求。
负责监听对 MySQL Server 的各种请求,接收连接请求,转发所有连接请求到线程管理模块。每一个连接上 MySQL Server 的客户端请求都会被分配(或创建)一个连接线程为其单独服务。而连接线程的主要工作就是负责 MySQL Server 与客户端的通信,
接受客户端的命令请求,传递 Server 端的结果信息等。线程管理模块则负责管理维护这些连接线程。包括线程的创建,线程的 cache 等。

4.SQL Interface: SQL接口

接受用户的SQL命令,并且返回用户需要查询的结果。比如select from就是调用SQL Interface

5.Parser: 解析器

SQL命令传递到解析器的时候会被解析器验证和解析。解析器是由Lex和YACC实现的,是一个很长的脚本。
在 MySQL中我们习惯将所有 Client 端发送给 Server 端的命令都称为 query ,在 MySQL Server 里面,连接线程接收到客户端的一个 Query 后,会直接将该 query 传递给专门负责将各种 Query 进行分类然后转发给各个对应的处理模块。
主要功能:
a . 将SQL语句进行语义和语法的分析,分解成数据结构,然后按照不同的操作类型进行分类,然后做出针对性的转发到后续步骤,以后SQL语句的传递和处理就是基于这个结构的。
b. 如果在分解构成中遇到错误,那么就说明这个sql语句是不合理的

6.Optimizer: 查询优化器

SQL语句在查询之前会使用查询优化器对查询进行优化。就是优化客户端请求的 query(sql语句) ,根据客户端请求的 query 语句,和数据库中的一些统计信息,在一系列算法的基础上进行分析,得出一个最优的策略,告诉后面的程序如何取得这个 query 语句的结果。

使用的是“选取-投影-联接”策略进行查询。

  • 用一个例子就可以理解: select uid,name from user where gender = 1;
  • 这个select 查询先根据where 语句进行选取,而不是先将表全部查询出来以后再进行gender过滤;
  • 这个select查询先根据uid和name进行属性投影,而不是将属性全部取出以后再进行过滤;
  • 将这两个查询条件联接起来生成最终查询结果。

7.Cache和Buffer: 查询缓存

主要功能是将客户端提交 给MySQL 的 Select 类 query 请求的返回结果集 cache 到内存中,与该 query 的一个 hash 值做一个对应。该 Query 所取数据的基表发生任何数据的变化之后, MySQL 会自动使该 query 的Cache 失效。在读写比例非常高的应用系统中, Query Cache 对性能的提高是非常显著的。当然它对内存的消耗也是非常大的。
如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key缓存,权限缓存等。

8.存储引擎接口

存储引擎接口模块可以说是 MySQL 数据库中最有特色的一点了。目前各种数据库产品中,基本上只有 MySQL 可以实现其底层数据存储引擎的插件式管理。这个模块实际上只是 一个抽象类,但正是因为它成功地将各种数据处理高度抽象化,才成就了今天 MySQL 可插拔存储引擎的特色。
从图2还可以看出,MySQL区别于其他数据库的最重要的特点就是其插件式的表存储引擎。MySQL插件式的存储引擎架构提供了一系列标准的管理和服务支持,这些标准与存储引擎本身无关,可能是每个数据库系统本身都必需的,如SQL分析器和优化器等,而存储引擎是底层物理结构的实现,每个存储引擎开发者都可以按照自己的意愿来进行开发。
注意:存储引擎是基于表的,而不是数据库。

并发控制

本节讨论Mysql在两个层面的并发控制:服务器层和存储引擎层

1.读写锁

在处理并发读或写时,可以通过实现一个由两种类型的锁组成的锁系统来解决问题。这两种类型的锁通常被称为共享锁或和排他锁,也叫读锁和写锁。
读锁是共享的,或者说是相互不阻塞的。多个客户在同一时刻可以同时读取同一个资源而不相互干扰
写锁是排他的,一个写锁会阻塞其他的写锁和读锁,Mysql锁的内部管理是透明的。

2.锁粒度

一种提高共享资源并发性的方式就是让锁定对象更有选择性。尽量只锁定需要修改的部分数据,而不是所有的资源。更理想的方式是,只对会修改的数据片进行精确的锁定。在给定的资源上,锁定的数据量越少,则系统的并发程度越高。所谓的锁策略,就是在锁的开销和数据的安全性之间寻求平衡。下面将介绍两种最重要的锁策略。

表锁

表锁的Mysql中最基本的锁策略,并且是开销最小的策略。它会锁定整张表,一个用户在对表进行写操作前,需要先获取写锁,这会阻塞其他用户对该表的所有读写操作。

行级锁

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

事务

事务就是一组原子性的sql查询,事务内的语句,要么全部执行成功,要么全部执行失败 。

转自 https://www.cnblogs.com/duanxz/p/5434276.html

MySQL 入门应用

MySQL 中的数据库(Database)就像是一个容器,其中包含了各种对象。例如,数据表(Table)、视图(View)、存储过程(Stored Procedure)以及触发器(Trigger)等。其中,表是存储数据的主要对象。
本篇主要介绍数据库的创建、查看、选择和删除操作,包括使用 mysql 命令行和 MySQL Workbench 图形工具两种方式。

通过 mysql 命令行管理数据库

存储数据需要先创建表,而创建表之前需要创建数据库。我们先使用 mysql 命令行客户端登录数据库,点击开始菜单 -> “MySQL” -> “MySQL 8.0 Command Line Client”,输入 root 用户密码:#####

1.创建数据库

MySQL 中使用CREATE DATABASE语句创建一个新的数据库:

CREATE DATABASE [IF NOT EXISTS] dbname;

其中,dbname 指定了新数据库的名称;IF NOT EXISTS是一个可选项,如果创建的数据库已经存在,使用该选项可以避免提示错误信息;数据库名称必须唯一。
举例来说,以下语句用于创建一个名为 hrdb 的数据库:

mysql> CREATE DATABASE hrdb;
Query OK, 1 row affected (0.27 sec)

那么,如何查看我们创建的数据库呢?MySQL 提供了SHOW DATABASES命令(不区分大小写)可以列出系统中的所有数据库:

mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| hrdb |
| information_schema |
| mysql |
| performance_schema |
| sakila |
| sys |
| world |
+--------------------+
7 rows in set (0.03 sec)

其中,information_schema、mysql、performance_schema 以及 sys 是 MySQL 的系统数据库。sakila 和 world 是我们安装的示例数据库。hrdb 是刚刚新建的数据库。显然,一个 MySQL 实例服务可以管理多个数据库。
MySQL 中的数据库和模式(Schema)是相同的概念,因此也可以使用SHOW SCHEMAS命令查看数据库列表。

2.字符集和排序规则

创建数据库时,还可以指定一些选项,例如字符集(Character Set)和排序规则(Collation)。
不同的字符集支持的字符种类和数量不同,例如 ASCII 字符集只能存储字母、数字和常见的符号,GB2312 和 GB18030 可以支持中文,Unicode 字符集能够支持多国语言。排序规则定义了字符的排序顺序,例如是否区分大小写、是否区分重音、中文按照拼音还是偏旁进行排序等。
因此,更完整的CREATE DATABASE语句如下:

CREATE DATABASE [IF NOT EXISTS] dbname
[CHARACTER SET charset_name]
[COLLATE collation_name];

CHARACTER SET选项用于指定字符集,如果不指定,默认为 utf8mb4;COLLATE选项用于指定排序规则,utf8mb4 字符集的默认排序规则为 utf8mb4_0900_ai_ci,表示不区分重音和大小写。
我们使用 GBK 字符集创建一个数据库 testdb:

mysql> create database testdb
-> character set gbk;
Query OK, 1 row affected (0.14 sec)

然后使用以下命令查看创建 testdb 数据库的语句:

mysql> show create database testdb;
+----------+---------------------------------------------------------------------------------------------------+
| Database | Create Database |
+----------+---------------------------------------------------------------------------------------------------+
| testdb | CREATE DATABASE `testdb` /*!40100 DEFAULT CHARACTER SET gbk */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+---------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

使用SHOW CHARACTER SET命令可以查看系统支持的所有字符集,使用SHOW COLLATION命令可以查看字符集支持的排序规则。

3.选择数据库

在访问表或者其他对象之前,我们必须告诉 MySQL 使用哪个数据库,不同数据库中可以存在同名的对象。MySQL 使用USE命令指定一个工作数据库:

USE dbname;

我们将 hrdb 设置为工作数据库:

mysql> USE hrdb;
Database changed

在此之后,我们执行的各种创建表、查询数据等操作都将在该数据库中进行;除非再次执行USE命令更改工作数据库。

4.删除数据库

删除数据库意味着同时删除数据库中的其他所有对象,并且不可恢复;因此执行之前需要十分小心!
MySQL 使用DROP DATABASE语句删除一个数据库:

DROP DATABASE [IF EXISTS] dbname;

其中,dbname 指定了要删除的数据库。IF EXISTS是一个可选项,如果被删除的数据库不存在,使用该选项可以避免提示错误信息。
我们将 hrdb 和 testdb 数据库删除:

mysql> drop database hrdb;
Query OK, 0 rows affected (0.17 sec)

mysql> drop database testdb;
Query OK, 0 row affected (0.23 sec)

mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sakila |
| sys |
| world |
+--------------------+
6 rows in set (0.00 sec)

再次查看数据库列表,显示 hrdb 和 testdb 不存在。
MySQL 中的数据库和模式(Schema)是相同的概念,因此也可以使用DROP SCHEMA命令删除数据库。

MySQL 进阶实战

prompt \u@ceshi \r:\m:s-> ###临时改变命令提示符
如果想永久生效放入my.conf里面的 [mysql]下面 prompt \u@ceshi \r:\m:s->

mysql登录

# mysql -h 127.0.0.1 -u mysql -P 3000   #远程连接  IP + 端口

mysql -h localhost -u root  -S /data/ops/app/mysql-5.6.23/3307/3307.sock 

MySQL修改root密码的多种方法

在 Navicat for MySQL 下面直接执行 SET PASSWORD FOR ‘root’@‘localhost’ = PASSWORD(‘newpass’); 就可以

**方法1: 用SET PASSWORD命令**
  mysql -u root
  mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpass');

**方法2:用mysqladmin**
  mysqladmin -u root password "newpass"
  如果root已经设置过密码,采用如下方法
  mysqladmin -u root password oldpass "newpass"
 
 **方法3: 用UPDATE直接编辑user表**
  mysql -u root
  mysql> use mysql;
  mysql> UPDATE user SET Password = PASSWORD('newpass') WHERE user = 'root';
  mysql> FLUSH PRIVILEGES;
在丢失root密码的时候,可以这样
  mysqld_safe --skip-grant-tables&
  mysql -u root mysql
  mysql> UPDATE user SET password=PASSWORD("new password") WHERE user='root';
  mysql> FLUSH PRIVILEGES;

##生产环境
./mysqld_safe --defaults-file=/data/ops/app/mysql-5.6.23/etc/3308.cnf --skip-grant-tables --user=mysql&
mysql> update mysql.user set password=password('123456') where user='root';
mysql> flush privileges;
mysqladmin -h127.0.0.1 -uroot -p shutdown ###输入密码123456

mysql -h127.0.0.1 -uroot -P3003 -p #输入密码登录成功123456

sql—日常操作

mysql> select user,host,password from mysql.user order by user; ##查询并排序
mysql> delete from mysql.user where user=' ';  ##删除用户
mysql> create database test;        创建数据库
mysql> show create database test\G #查看创建数据库,默认创建字符集latin1
mysql> create database test_gbk DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci; ###创建指定的字符集数据库
mysql> show create dabases test_gbk\G  ##查看创建的数据库发现字符集变成gbk
mysql> create database test_utf8 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; ###创建utf8数据库
mysql> show create dabases test_utf8\G ##查看创建的数据库字符集变成utf8
 
##提示 字符集的不一致是数据库中午乱码的罪魁祸首,有关字符集的看后面
##提示 如果变异的时候指定了字符集 以后创建数据库就不需要指定了
企业里:
1根据开发的程序确定字符集(建议用utf8)
2.编译的时候指定字符集
3.编译的时候没有指定字符集或者指定了和程序不同的字符集,如果解决?   ###指定字符集创建数据库即可。
 
**显示数据库:**
show databases;
select database();

**删除数据库:**
mysql> drop database test;

**切换数据库:**
use test_utf8;

**查看版本:**
select version();

**查看当前用户:**
select user();

**查看当前时间:**
select now();

**创建用户:**
mysql> create user 'haha'@'localhost' identified by '123';

**删除用户:**
mysql> drop user 'haha'@'localhost';

**创建并授权:**
grant all privileges on test.* to oldboy@'localhost' identified by 'oldboy123';

**查看用户权限:**
mysql> show grants for oldboy@localhost;

**只授权:**
grant all ON test.* to 'haha'@'localhost';

**远程授权:**
mysql> create user test@'10.0.0.%' identified by 'test';
 
**回收权限:**
mysql> show grants for oldboy@localhost;
+---------------------------------------------------------------------------------------------------------------+
| Grants for oldboy@localhost                                                                                   |
+---------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'oldboy'@'localhost' IDENTIFIED BY PASSWORD '*FE28814B4A8B3309DAC6ED7D3237ADED6DA1E515' |
| GRANT ALL PRIVILEGES ON `test`.* TO 'oldboy'@'localhost'                                                      |
+---------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
 
mysql> revoke insert on test.* from 'oldboy'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for oldboy@localhost;
企业环境尽量最小化权限,只给增删改查,把创建删除收回。
 
 
**创建表:**
mysql> create table tutorials_tbl(    tutorial_id INT NOT NULL AUTO_INCREMENT,    tutorial_title VARCHAR(100) NOT NULL,    tutorial_author VARCHAR(40) NOT NULL,    submission_date DATE,    PRIMARY KEY ( tutorial_id ) );

**查看表结构:**
mysql> desc tutorials_tbl;
mysql> show create table tutorials_tbl;

转自 https://www.cnblogs.com/zhaobin-diray/p/9355473.html

你可能感兴趣的:(运维-Liunx)