- 我们在开发的时候,我们都需要对业务数据进行存储,这个时候,你们就会用到MySQL、Oracal等数据库。
- MySQL它是一个关系型数据库,这种关系型数据库就有Oracal、 MySQL,以及最近很火的PgSQL等。
- 就是它是基于我们的SQL语句去执行操作的。
- 其实就是关系表数据库,由表结构来存储数据与数据之间的关系,同时用SQL(Structured query language)结构化查询语句来进行数据操作。
- 关系型数据库,对应会有一个非关系型数据库,像我们用的比较多的 Redis 这种Key - Value结构数据存储、hbase这种列存储格式、MongoDB这种文档存储等等。
- 关系型数据库都是用表来进行维护,所以格式一致,可以统一用SQL语言来进行操作
- 关系型数据库都是表结构,所以灵活度不够,操作复杂的海量数据性能比较差,所以我们才会有表结构、索引以及索引优化。
- 虽然性能可能会比较慢,但是能做复杂的关联查询操作。 比如一对一, 一对多,多对多等等。
- 易用性:开发者可以在几分钟内安装好MySQL,数据库易于管理。
- 可靠性: MySQL 是最成熟、使用最广泛的数据库之一。超过 25 年,它已经在各种场景中进行了测试,其中包括许多世界上最大的公司。由于MySQL 的可靠性,组织依赖 MySQL 来运行关键业务应用程序。
- 可扩展性: MySQL 可扩展以满足最常访问的应用程序的需求。MySQL 的本机复制架构使 Facebook 等组织能够扩展应用程序以支持数十亿用户。
- 高性能: MySQL HeatWave比其他数据库服务更快且成本更低,多项标准行业基准测试证明了这一点,包括 TPC-H、TPC-DS 和 CH-benCHmark。
- 高可用性: MySQL 为高可用性和灾难恢复提供了一套完整的本机、完全集成的复制技术。对于关键业务应用程序,并满足服务级别协议承诺,客户可以实现 零数据丢失以及秒级的故障转移恢复。
- 安全性: 数据安全需要保护和遵守行业和政府法规,包括欧盟通用数据保护条例、支付卡行业数据安全标准、健康保险可移植性和责任法案以及国防信息系统局的安全技术实施指南。MySQL 企业版提供高级安全功能,包括身份验证/授权、透明数据加密、审计、数据屏蔽和数据库防火墙。
- 灵活性: MySQL 文档存储为用户开发传统 SQL 和 NoSQL 无模式数据库应用程序提供了最大的灵活性。开发人员可以在同一个数据库和应用程序中混合和匹配关系数据和 JSON 文档。
查询所有的库:
创建库:
查询当前选择的库:
官网:MySQL :: MySQL 8.0 参考手册 :: 5.3 mysql 系统架构
- mysql库:这一个系统库是来保证我的数据库服务正常运行的一个系统表全部在这个库里面。
- information_schema库:包括InnoDB里面的数据、日志、事务、表;还有PROCESSLIST表:它记录了当前正在运行的数据库有多少个连接和查询进程的信息;ENGINES表:存储引擎插件表。
- performance_schema库 - 性能库:这个库里面所有的数据是当前只存在内存里面的,这个库下面所有的事件、锁(比如data_locks表) - 我会去锁哪些数据。这些数据它只针对我当前的服务,如果重启了,所有的数据会丢失,所以这个它只存在当前内存。
show variables like 'general_log'; //一般查询日志,默认关闭
SELECT @@long_query_time;
show global variables like 'long_query_time';
show global variables like 'min_examined_row_limit'; //至少需要检索这么多行
show global variables like 'slow_query_log'; //是否开启慢日志查询 默认关闭
SET GLOBAL slow_query_log=1;
set global long_query_time=0.1; //超过100毫秒
log_output=table |file |none //设置是放在文件中,还是在mysql.slow_log表中
MySQL的四个线程状态变量:MySQL :: MySQL 8.0 参考手册 :: 5.1.6 服务器状态变量参考
- Thread_cached:是MySQL的一个状态变量,表示MySQL线程缓存中当前缓存的线程数,是为了我的服务,不用每一次客户端建立连接的时候都去创建一个线程,以此减少线程的创建和销毁的开销,提高数据库性能,所以它有一个缓存的线程数。当一个客户端连接到MySQL数据库服务器时,服务器会为该连接创建一个线程来处理客户端的请求。线程缓存的作用就是在该连接请求结束后,将这些线程缓存在内存中,以便下次有新的连接请求时能够复用这些线程,而不需要重新创建。thread_cache_size是MySQL的一个静态配置参数,用来配置线程缓存的大小,默认是-1,需要手动调整(在MySQL配置文件当中配置)并重启MySQL服务才能生效,最大是16384。
- Thread_connected:我当前打开的线程数,就是我现在有多少个线程是打开的。
- Thread_created:总共创建的线程数,即创建的线程总数。创建的线程总数越多,我们的thread_cache_size 可以对应的更大,来提升线程的缓存命中率。
- Threads_running:正在运行的线程数
-- 查看MySQL的四个Thread线程状态变量
show status like 'Thread%';
-- 查询thread_cache_size系统变量
select @@thread_cache_size;
-- 显示当前正在运行的线程
show full PROCESSLIST;
id:线程 ID
State:连接状态
User:操作的用户名
Host:主机 / IP
db:操作的数据库
command:当前连接执行的命令:Sleep-休眠、Query-查询
Time:这个状态持续的时间,单位是s
info - 信息:查询会有查询的信息,但是长度有限制,可能不全
使用PROCESSLIST表可以查看当前正在运行的连接-线程,假如当前有客户端连接已经阻塞了,那么此时你可以去把它KILL掉:
SELECT * FROM product_new --表中有500W数据,查询很慢
2. 会话二:
SHOW PROCESSLIST; -- 查看当前线程
执行结果:
3. 关闭查询query:
KILL QUERY 9328; -- 终止查询
4. 杀死 / 关闭连接线程 - Connection Thread
KILL 2280; -- kill 连接线程
查看会话一的结果:
show status like 'Max_used_connections%';
-- 查询最大连接数 默认151
SELECT @@max_connections;
select @@GLOBAL.max_connections;
-- 手动设置最大连接数
SET @@GLOBAL.max_connections = 1000;
-- 查询服务器超时等待时间 默认28800s - 8h
SELECT @@wait_timeout;
select @@GLOBAL.wait_timeout;
-- 手动设置服务器最大等待时间
SET @@GLOBAL.wait_timeout = 1000;
- max_connections:最大的连接数,即我的服务最多能开启的连接数,超过该值不允许建立连接,默认151,最小1,最大 100000。如果开启太大,同时会有很多的客户端来进行连接操作,MySQL性能可能会跟不上;如果开启太小,可能在高并发场景下导致并发量上不来。
- wait_timeout:最大的等待时间 / 服务器超时等待时间 / 非交互连接等待的时间(单位s),默认28800s,也就是8小时,用于指定一个连接在空闲状态下的最长等待时间。如果一个连接在8小时内没有进行任何操作,那么MySQL服务器会自动关闭该连接,以释放资源。wait_timeout => 服务器什么时候会自动关闭?
跟服务器建立完连接之后,此时就代表客户端能跟服务端去进行通信了,也就是客户端能向服务端去发送SQL语句的请求了。
- 提升性能
- 防止SQL注入,更安全
MyBatis中的SQL注入是MyBatis去做的参数化,而这里的SQL注入是我们的MySQL服务器自己能支持的,预处理器它是我们的MySQL服务能支撑的。
- 以我们的工作场景为例,一个查询接口,SQL语句都是一样的,但是每次查询的参数都不一样,所以我们想只需要变更参数部分就行。
- 那么,我们就是在拼接SQL语句的时候,将用户的输入跟语句拼接成一个SQL语句给到MySQL执行。
- 但是会发生一个SQL注入问题!
-- 要执行的SQL语句
select * from emp where password = '';
-- SQL注入演示-客户端传入查询的参数为: ' or '1' = '1
select * from emp where password = '' or '1' = '1';
- 首先在应用程序中,应该去创建一个预处理语句,将SQL查询与占位符(通常使用问号?来表示)组合起来,形成一个带有参数占位符的SQL查询语句。
- 接着,应用程序将这个预处理语句发送到MySQL服务器进行编译。服务器会对SQL语句进行语法解析和执行计划生成,但不会执行实际的查询。
- 在执行查询之前,应用程序通过绑定参数的方式将实际的参数值与占位符关联起来,这样可以防止SQL注入攻击,因为用户输入的参数不会直接嵌入到查询语句中,而是作为参数传递给服务器,并允许在多次执行中重复使用预处理语句(因为预处理语句只需编译一次,再次执行时就无需重新编译,以此提高性能)。
- 一旦参数绑定完成,应用程序可以多次执行相同的预处理语句,通过更改参数值来获取不同的结果。
-- 创建预处理语句
-- PREPARE 预处理名字 from 'SQL语句';
PREPARE select_user from 'select * from emp where password = ?'
-- 绑定参数(设置参数值)
SET @passsword = '123456';
-- 执行预处理语句
-- EXECUTE 预处理名字 USING @绑定参数名;
EXECUTE select_user USING @passsword;
-- 清除预处理语句
-- DEALLOCATE PREPARE 预处理名字;
DEALLOCATE PREPARE select_user;
- #符号执行SQL时,会将#{...}替换成?,生成预编译SQL / 预处理SQL,然后进行预处理,能防止SQL注入,并且必须传入参数;
- $符号会拼接SQL,直接将${...}参数拼接在SQL语句中,存在SQL注入问题。
-- 获取MySQL数据库中的全局优化器开关配置信息
SELECT @@GLOBAL.optimizer_switch;
- 优化器说明:https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html,里面包含了每个优化选项说明.
- 优化方式官网地址:https://dev.mysql.com/doc/refman/8.0/en/optimization.html;这个里面就有很多优化器的实践,比如优化sql语句等等。
- 优化器它是基于服务,觉得自己最快的一些方式去执行这个语句,优化后会生成一个最优的执行计划,并将该执行计划传递给存储引擎层,所以这个语句到底怎么走,优化器来决定。
- 它是基于内存与CPU或性能的消耗得到一个算法或者说得到哪一个执行计划它是最快的。
- 当前,优化器里面有一些东西它是可以自己设置的,比如说要不要索引下推,比如说要不要回表,比如说要不要去用联合索引,要不要用hash_join,要不要用跳跃扫描skip_scan,要不要用mrr,mrr是它底层的一个算法,能够更快的跟我的磁盘去进行交互等等。
- 根据执行计划,去调用数据存储的地方,也就来到了我们MySQL Server中的第三层 - 存储引擎层!
刚刚讲了 MySQL的很多插件 , 但是还没有真正的去跟数据交互 ,也就是没有去查询数据。 数据是放在我们的MySQL Server中的存储引擎层。- 存储引擎层是真正的跟数据进行交互的,是真正的来保存以及怎么去查询数据的,所以存储引擎层决定了我这个数据以什么样子的方式来保存,比如说你是保存到磁盘,还是保存到内存,还是磁盘跟内存都有。
- 执行器去根据表设置的存储引擎,调用不同存储引擎的API接口获取数据。
- 至于这个数据是怎么存的,这个数据有哪些优化(比如内存去缓存)等等,就是每个存储引擎自己去做的事情,也就来到了我们MySQL Server中的第三层中的存储引擎层,并且存储引擎是跟MySQL解耦的,存储引擎跟MySQL的开发者都不是同一批人。
- 存储引擎它是我们MySQL的一个插件,你如果有能力,MySQL都支持你自己写存储引擎。
- 基于不同的一些场景,比如说有一些场景我要去保证性能,有一些场景我要去保证一致性,所以它会有不同的存储方案,这里就牵扯到我们不同的存储引擎。
MySQL支持不同的存储引擎,这些存储引擎决定了我们数据的存储方式,以及数据的可靠性、一致性、持久性、原子性。也就是我们经常讲的ACID。
可以通过语句查询当前服务器支持哪些存储引擎:
SHOW ENGINES; -- 查询当前服务器支持的存储引擎
不同的存储引擎会有自己不同的存储实现方式 / 存储方案,不管是什么存储引擎,它一定要做的事情是把这个数据保存起来,是用内存还是磁盘,还是都用,或者磁盘的文件格式等等都会不一样。
SQL语句查询:
-- 查询数据库的数据目录
select @@datadir;
show variables like '%datadir%';
该目录就是我们的数据库的数据目录,我们的数据保存在该目录下。