开办网站备案成都网站建设 seo

news/2025/9/23 12:25:42/文章来源:
开办网站备案,成都网站建设 seo,国家电网网站制作,搜搜提交网站1. MySQL 基础篇 1.1 MySQL 概述 1.1.1 数据库相关概念 数据库(Database, 简称 DB): 存储数据的仓库#xff0c;数据是有组织的进行存储。 数据库管理系统(Database Management System, 简称 DBMS): 操作和管理数据库的大型软件。 SQL(Structured Query Language, 简称 S…1. MySQL 基础篇 1.1 MySQL 概述 1.1.1 数据库相关概念 数据库(Database, 简称 DB): 存储数据的仓库数据是有组织的进行存储。 数据库管理系统(Database Management System, 简称 DBMS): 操作和管理数据库的大型软件。 SQL(Structured Query Language, 简称 SQL): 操作关系型数据库的编程语言定义了一套操作关系型数据库的统一标准。 主流的关系型数据库管理系统 OracleMySQLMicrosoft SQL ServerPostgreSQLIBM Db2Microsoft AccessSQLiteMariaDBMicrosoft Azure SQL DatabaseHive 1.1.2 MySQL 数据库 MySQL 官方提供了两种不同的版本 社区版(MySQL Community Server): 免费MySQL 不提供任何技术支持。商业版(MySQL Enterprise Edition): 收费可以试用 30 天官方提供技术支持。 MySQL Community Server 下载地址 MySQL数据库的数据模型 关系型数库(Relational Database Management System,简称RDBMS)建立在关系模型基础上由多张相互连接的二维表组成的数据库。 关系型数据库的特点 使用表存储数据格式统一便于维护。使用 SQL 语言操作标准统一使用方便。 1.2 SQL 1.2.1 SQL通用语法 SQL语句可以单行或多行书写以分号结尾。SQL语句可以使用空格/缩进来增强语句的可读性。MySQL 数据库的SQL语句不区分大小写关键字建议使用大写。注释 单行注释–注释内容或 # 注释内容(MySQL特有)多行注释/* 注释内容 */ 1.2.2 SQL分类 DDL(Data Definition Language): 数据定义语言用来定义数据库对象(数据库、表、字段)DML(Data Manipulation Language)数据操作语言用来对数据库表中的数据进行增删改DQL(Data Query Language): 数据查询语言用来查询数据库中表的记录。DCL(Data Control Language): 数据控制语言用来创建数据库用户控制数据库的访问权限 1.3 函数 函数 是指一段可以直接被另一段程序调用的程序或代码。 函数分类 字符串函数数值函数日期函数流程函数 字符串函数 concat(s1,s2,…,sn): 字符串拼接lower(str): 将字符串转为小写upper(str): 将字符串转为大写lpad(str,n,pad): 左填充rpad(str,n,pad): 右填充trim(str): 去掉字符串头部和尾部的空格。substring(str,start, len): 返回从字符串str 从 start 位置起的 len 个长度的字符串。 数值函数 ceil(x): 向上取整floor(x): 向下取整mod(x,y): 返回x和y的模rand(): 返回 0-1 内的随机数round(x,y): 求参数 x 的四舍五入值保留y位小数。 日期函数 curdate(): 返回当前日期curtime(): 返回当前时间now(): 返回当前日期和时间year(date): 获取指定 date 的年份month(date): 获取指定 date 的月份day(date): 获取指定 date 的日期date_add(date, interval expr type): 返回一个日期/时间值加上一个时间间隔 expr 后的时间值datediff(date1, date2): 返回起始时间 date1 和 结束时间 date2 之间的天数。 流程函数 if(value, t, f): 如果 value 为true, 则返回 t, 否则返回 f。ifnull(value1, value2): 如果 value 不为空 则返回 value1否则返回 value2.case when [val1] then [res1] … else [default] end: 如果 val1 为 true, 返回 res1… 否则返回 default 默认值。case [expr] when [val1] then [res1] … else [default] end: 如果 expr 的值等于 val1, 返回 res1否则返回 default 默认值。 1.4 约束 1.4.1 约束概述 约束是作用于表中字段上的规则用于限制存储在表中的数据。 目的保证数据库中的数据正确、有效性和完整性。 常见约束 非空约束(not null)限制该字段的数据不能为 null唯一约束(unique)保证该字段的所有数据都是唯一的、不重复的主键约束(primary key): 主键是一行数据的唯一标识要求非空且唯一。默认约束(default):保存数据时如果未指定该字段的值则采用默认值。检查约束(check, 8.0.16版本之后支持)保证字段满足某一个条件外键约束(foreign key): 用来让两张表的数据建立连接保证数据的一致性和完整性。 约束是作用于表中字段上的可以在创建表/修改表的时候添加约束。 建表时添加约束示例 create table user (id int primary key auto_increment comment 主键,name varchar(10) not null unique comment 姓名,age int check(age 0 age 120) comment 年龄status char(1) default 1 comment 状态,gender char(1) comment 性别 ) comment 用户表;1.4.2 外键约束 外键用来让两张表的数据之间建立连接从而保证数据的一致性和完整性。 添加外键 -- 新建表时 create table 表名 (字段名 字段类型,...[constraint] [外键名称] foreign key (外键的字段名) references 主表(主表列名) ); -- 修改表时 alter table 表名 add constraint 外键名称 foreign key (外键字段名) references 主表(主表列名);外键约束删除/更新行为 no action: 当在父表中删除/更新对应记录时首先检查该记录是否有对应外键如果有则不允许删除/更新。restrict: 当在父表中删除/更新对应记录时首先检查该记录是否有对应外键如果有则不允许删除/更新。cascade: 当在父表中删除/更新对应记录时首先检查该记录是否有对应外键如果有则也删除/更新外键在子表中的记录。set null: 当在父表中删除对应记录时首先检查该记录是否有对应外键如果有则设置子表中该外键的值为 null(这就要求该外键取null)set default: 父表有变更时子表将外键列设置成一个默认值(innodb 不支持) 指定外键约束删除/更新行为 alter table 表名 add constraint 外键名称 foreign key (外键的字段名) references 主表(主表列名) on update cascade on delete cascade;1.5 多表查询 1.5.1 多表关系 项目开发中在进行数据库表设计时会根据业务需求及业务模块之间的关系分析并设计表结构由于业务之间相互关联所以各个表之间也存在各种联系基本上分为三种 一对多 (多对一): 实现是在多的一方建立外键指向一的一方的主键。多对多实现是建立第三张中间表中间表至少包含两个外键分别关联两方主键。一对一实现是在任意一方加入外键关联另一方的主键并且设置外键为唯一的(unique) 1.5.2 多表查询的概述 多表查询是能从多张表中查询数据 笛卡尔积笛卡尔乘积是指在数学中两个集合A集合和B集合的所有组合情况。(在多表查询中需要消除无效的笛卡尔积)。 多表查询的分类: 连接查询 内连接相当于查询A、B的交集部分外连接 左外连接查询左表所有数据以及两张表交集部分的数据。右外连接查询右表所有数据以及两张表交集部分的数据。 自连接当前表与自身的连接查询自连接必须使用表别名。 子查询 内连接: -- 隐式内连接 select 字段列表 from 表1表2 where 条件 -- 显式内连接 select 字段列表 from 表1 [inner] join 表2 on 连接条件;外连接 -- 左外连接 select 字段列表 from 表1 left [outer] join 表2 on 条件; -- 右外连接 select 字段列表 from 表1 right [outer] join 表2 on 条件;自连接 select 字段列表 from 表A 别名A join 表A 别名B on 条件;联合查询 union、union all 对于 union 查询就是把多次查询结果合并起来形成一个新的查询结果集。 select 字段列表 from 表A ... union [all] select 字段列表 from 表B ...;union all 是直接将查询结果合并union 是将查询结果合并后去重。 对于联合查询的多张表的列数必须保持一致字段类型也需要保持一致。 1.5.3 子查询 SQL 语句中嵌套 SELECT 语句称为嵌套查询又称子查询。 select * from t1 where col1 (select column1 from t2);子查询的外部语句可以是 INSERT/UPDATE/DELETE/SELECT 的任何一个。 根据子查询结果不同分为 标量子查询子查询结果为单个值列子查询子查询结果为一列行子查询子查询结果为一行表子查询子查询结果为多行多列 根据子查询出现的位置分为 where 之后from 之后select 之后 标量子查询: 子查询返回的结果是单个值(数字、字符串、日期等)最简单的形式。 常用的操作符、、、、、 列子查询子查询返回的结果是一列(可以是多行)。 常用操作符 in在指定的集合范围内多选一。not in不在指定的集合范围之内。any子查询返回列表中有任意一个满足即可。some与any等同使用some的地方都可以使用 any。all子查询返回列表的所有值都必须满足。 行子查询子查询返回的结果是一行(可以是多列)。 常用操作符、、in、not in 表子查询子查询返回的结果是多行多列。 常用操作符in 1.6 事务 1.6.1 事务简介 事务是一组操作的集合它是一个不可分割的工作单位事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求即这些操作要么同时成功要么同时失败。 默认MySQL的事务是自动提交的也就是说当执行一条DML语句MySQL会立即隐式的提交事务。 1.6.2 事务操作 查看/设置事务的提交方式 select autocommit; -- 0 是手动提交事务1 是自动提交事务 set autocommit0;开启事务 -- 方式一 start transaction -- 方式二 begin提交事务 commit;回滚事务 rollback;1.6.3 事务四大特性 原子性(Automicity): 事务是不可分割的最小操作单元要么全部成功要么全部失败。一致性(Consistency)事务完成时必须使所有的数据都保持一致状态。隔离性(Isolation)数据库系统提供的隔离机制保证事务在不受外部并发操作影响的独立环境下运行。持久性(Durability)事务一旦提交或回滚它对数据库中的数据的改变就是永久的。 1.6.4 并发事务问题 脏读一个事务读到另一个事务还没有提交的数据。不可重复读一个事务先后读取同一条记录但两次读取的数据不同。幻读一个事务按照条件查询数据时没有对应的数据行但是在插入数据时又发现这行数据已经存在好像出现了幻影。 1.6.5 事务隔离级别 隔离级别脏读不可重复读幻读read uncommitted✔✔✔read committed✖✔✔repeattable read(默认)✖✖✔serializable✖✖✖ 查看事务隔离级别 select transaction_isolation设置事务隔离级别 set [session | global] transaction isolation level { read uncommitted | read committed | repeatable read | serializable}2. MySQL 进阶篇 2.1 存储引擎 2.1.1 MySQL 体系结构 连接层最上层是一些客户端和链接服务主要完成一些类似于连接处理、认证授权、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。服务层第二层架构主要完成大多数的核心服务功能如SQL接口并完成缓存查询SQL的分析和优化部分内置函数的执行。所有跨存储引擎的功能也在这一层实现如过程、函数等。引擎层存储引擎真正的负责了MySQL中数据的存储和提取服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能这样我们可以根据自己的需要来选取合适的存储引擎。存储层主要是将数据存储在文件系统之上并完成与存储引擎的交互。 2.1.2 存储引擎简介 存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的而不是基于数据库的所以存储引擎也可被称为表类型。 在建表时指定存储引擎 create table 表名(字段 字段类型 [comment 字段注释] ) engine InnoDB [comment 表注释];查看当前数据库支持的存储引擎 show engines;2.1.3 存储引擎特点 2.1.3.1 InnoDB 存储引擎 InnoDB 是一种兼顾了高可靠性和高性能的通用存储引擎在 MySQL 5.5 之后InnoDB 是默认的 MySQL 存储引擎。 InnoDB 特点 DML 操作遵循 ACID 模型支持事务。行级锁提高并发访问性能支持外键 FOREIGN KEY 约束保证数据的完整性和约束。 InnoDB 文件 xxx.ibd: xxx代表表名innoDB引擎的每张表都会对应这样一个表空间文件存储该表的表结构 (frm、sdi)、数据和索引。 参数innodb_file_per_table决定表空间中表的数量。 -- 如果值为 ON,则一张表对应一个表空间。 show variables like innodb_file_per_table;# 查看 ibd 文件中的表结构 ibd2sdi xxx.ibdInnoDB 逻辑存储结构 2.1.3.2 MyISAM 存储引擎 MyISAM 是MySQL早期的默认存储引擎。 MyISAM 特点 不支持事务不支持外键支持表锁不支持行锁访问速度快 MyISAM 文件 xxx.sdi:存储表结构消息数据格式为jsonxxx.MYD:存储数据xxx.MYI:存储索引 2.1.3.3 Memory 存储引擎 Memory 引擎的表数据是存储在内存中的由于受到硬件问题、或断电问题的影响只能将这些表作为临时表或缓存使用。 Memory 特点 内存存放hash索引(默认) Memory 文件 xxx.sdi: 存储表结构消息 2.1.3.3 InnoDB、MyISAM、Memory 存储引擎对比 特点InnoDBMyISAMMemory存储限制64TB有有事务安全支持锁机制行锁表锁表锁Btree 索引支持支持支持Hash 索引支持全文索引支持(5.6版本之后)支持空间使用高低N/A内存使用高低中等批量插入速度低高高支持外键支持 2.1.4 存储引擎的选择 在选择存储引擎时应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统还可以根据实际情况选择多种存储引擎进行组合。 适用场景 InnoDB是 MySQL的默认存储引擎支持事务、外键。如果应用对事务的完整性有比较高的要求在并发条件下要求数据的一致性数据操作除了插入和查询外还包含很多的更新、删除操作那么InnoDB的存储引擎是比较合适的选择。MyISAM: 如果应用是以读操作和插入操作为主只有很少的更新和删除操作并且对事务的完整性、并发性要求不是很高那么选择这个存储引擎是非常合适的。Memory: 将所有数据保存到内存中访问速度快通常用于临时表及缓存。Memory的缺陷就是对表的大小有限制太大的表无法缓存到内存中而且无法保障数据的安全性。 2.2 索引 2.2.1 索引概述 索引(index) 是帮助 MySQL 高效获取数据的数据结构(有序)。 在数据之外数据库系统还维护着满足特定查找算法的数据结构这些数据结构以某种方式引用(指向)数据这样就可以在这些数据结构上实现高级查找算法这种数据结构就是索引。 索引的优点 提高数据检索效率降低数据库的IO成本。通过索引列对数据进行排序降低数据排序的成本降低 CPU 的消耗。 索引的缺点 索引列也是要占用空间的。索引大大提高了查询效率同时却也降低更新表的速度如对表进行 insert、update、delete时效率降低。 2.2.2 索引结构 MySQL 的索引是在存储引擎层实现的不同的存储引擎有不同的结构主要包含以下几种 BTree 索引最常见的索引类型大部分引擎都支持 B 树索引。Hash 索引底层数据结构使用哈希表实现的只有精确匹配索引列的查询才有效不支持范围查询。R-tree(空间索引)空间索引是 MyISAM 引擎的一个特殊索引类型主要用于地理空间数据类型通常使用较少。Full-text(全文索引)是一种通过建立倒排索引快速匹配文档的方式。类似于 Lucene、Solr、ES 索引类型在各个存储引擎中的支持情况 索引InnoDBMyISAMMemoryBtree 索引支持支持支持Hash 索引不支持不支持支持R-tree 索引不支持支持不支持Full-text5.6版本之后支持支持不支持 2.2.2.1 Btree 索引结构 二叉树顺序插入时会形成一个链表查询性能大大降低。大数据量情况下层级较深检索速度慢。 红黑树大数据量情况下层级较深检索速度慢。 B-Tree (多路平衡查找树) 以一颗最大度数(max-degree)为 5(5阶) 的 b-tree 为例(每个节点最多存储4个key,5个指针) 树的度数指的是一个节点的子节点个数。 BTree: 以一颗最大度数(max-degree)为 4(4阶) 的 btree 为例 BTree 相对于 B-Tree 的区别: 所有数据都会出现在叶子节点叶子节点形成一个单向链表 MySQL 中 BTree 的结构: MySQL 索引数据结构对经典的 BTree 进行了优化。在原 BTree 的基础上增加一个指向相邻叶子节点的链表指针就形成了带有顺序指针的 BTree, 提高区间访问性能。 2.2.2.2 Hash 索引结构 哈希索引就是采用一定的 hash 算法将键值换算成新的 hash 值映射到对应的槽位上然后存储在 hash 表中。 Hash 索引的特点: Hash 索引只能用于对等比较 (, in), 不支持范围查询 (between…)无法利用索引完成排序操作查询效率高通常只需要一次检索就可以了效率通常要高于 Btree 索引。 存储引擎支持: 在 MySQL 中支持 Hash 索引的是 Memory 引擎而 InnoDB 中具有自适应 hash 功能hash 索引是存储引擎根据 BTree索引在指定条件下自动构建的。 2.2.3 索引分类 分类含义特点关键字主键索引针对表中主键创建的索引默认自动创建只能有一个PRIMARY唯一索引避免同一表某数据列中的值重复可以有多个UNIQUE常规索引快速定位特定数据可以有多个全文索引全文索引查找的是文本中的关键字而不是比较索引中的值可以有多个FULLTEXT 在 InnoDB 存储引擎中根据索引的存储形式又可以分为以下两种 分类含义特点聚集索引 (Clustered Index)将数据存储和索引放到了一块索引结构的叶子节点保存了行数据必须有而且只有一个二级索引 (Secondary Index)将数据和索引分开存储索引结构的叶子节点关联的是对应的主键可以存在多个 聚集索引选取规则 如果存在主键主键索引就是聚集索引。如果不存在主键将使用第一个唯一(unique)索引作为聚集索引。如果表没有主键或没有合适的唯一索引则 InnoDB 会自动生成一个 rowid 作为隐藏的聚集索引。 回表查询: 先查二级索引获取主键再查聚集索引获取行数据。 2.2.4 索引语法 创建索引: create [UNIQUE | FULLTEXT] index index_name on table_name (index_col_name, ...);查看索引: show index from table_name;删除索引: drop index index_name on table_name;2.2.5 SQL性能分析 2.2.5.1 SQL执行频率 MySQL 客户端连接成功后通过 show[session|global] status 命令可以提供服务器的状态信息。通过如下指令可以查看当前数据库的 INSERT、UPDATE、DELETE、SELECT的访问频次。 -- 查询SQL执行频率 show global status like Com_______;2.2.5.2 慢查询日志 慢查询日志记录了所有执行时间超过指定参数(long_query_time, 单位秒默认10秒)的所有SQL语句的日志。 -- 查询数据库是否开启慢查询日志 show VARIABLES like slow_query_log;MySQL 的慢查询日志默认没有开启需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息 # 开启 MySQL 慢日志查询开关 slow_query_log1 # 设置慢日志的时间为2秒SQL语句执行时间超过2秒就会视为慢查询记录慢查询日志 long_query_time2;配置完毕之后通过以下指令重新启动MySQL服务器进行测试查看慢日志文件中记录的信息 /var/lib/mysql/localhost-slow.log # 重启 MySQL 服务 systemctl restart mysqld.service2.2.5.3 profile详情 show profiles 能够在做 SQL 优化时帮助我们了解时间耗费到哪里去了通过 have_profiling 参数能够看到当前 MySQL 是否支持 profile 操作 -- 查询是否支持 profile 详情 select have_profiling; -- 查询 profiling 是否开启1 开启0 关闭 select profiling; -- 可以通过 set 语句在 session/global 级别开启 profiling set progiling 1; -- 查看每一条SQL的耗时基本情况 show profiles; -- 查看指定 query_id 的 SQL 语句各个阶段的耗时情况 show profile for query query_id; -- 查看指定 query_id 的 SQL 语句 CPU 的使用情况 show profile cpu for query query_id;2.2.5.4 explain 执行计划 explain 或者 DESC 命令获取 MySQL 如何执行 SELECT 语句的信息包括在 SELECT 语句执行过程中表如何连接和连接的顺序。 -- 直接在 select 语句之前加上 explain/desc; explain select 字段列表 from 表面 where 条件;Explain 执行计划各字段的含义 idselect 查询的序列号表示查询中执行 select 子句或者是操作表的顺序(id相同执行顺序从上到下id不同值越大越先执行)。select_type表示 select 的类型常见的取值有 SIMPLE(简单表即不使用表连接或者子查询)、PRIMARY(主查询即外层的查询)、UNION(UNION 中的第二个或后面的查询语句)、SUBQUERY(SELECT/WHERE之后包含了子查询)等type表示连接的类型性能的由好到差的连接类型为 NULL、system、const、eq_ref、ref、range、index、all。possible_key显示可能应用在这张表上的索引一个或多个。Key实际使用的索引如果为 NULL,则没有使用索引。Key_len表示索引中使用的字节数该值为索引字段最大可能长度并非实际使用长度在不损失精确性的前提下长度越短越好。rowsMySQL 认为必须要执行查询的行数在 innoDB 引擎的表中是一个估计值可能并不总是准确的。filtered表示返回结果的行数占需读取行数的百分比filtered 的值越大越好。Extra额外的数据。 2.2.6 索引使用 最左前缀法则 如果索引了多列(联合索引)要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始并且不跳过索引中的列。 如果跳跃某一列索引将部分失效(后面的字段索引失效)。 范围查询 联合索引中出现范围查询(,),范围查询右侧列索引失效。 索引列运算 不要在索引列上进行运算操作索引将失效。 字符串不加引号 字符串类型字段使用时不加引号索引将失效。 模糊查询 如果仅仅是尾部模糊匹配索引将不会失效。如果是头部模糊匹配。索引将失效。 or连接的条件 用or分割开的条件如果or前的条件中的列有索引而后面的列中没有索引那么涉及的索引都不会被用到。 数据分布影响 如果MySQL评估使用索引比全表更慢则不使用索引。 SQL提示 SQL 提示是优化数据库的一个重要手段简单来说就是在SQL语句中加入一些人为的提示来达到优化操作的目的。 -- use index 建议使用的索引 explain select * from user use index(idx_user_name) where name test; -- ignore index 忽略索引 explain select * from user ignore index(idx_user_name) where name test; -- force index 强制使用的索引 explain sekect * from user force index(idx_user_name) where name test;覆盖索引 尽量使用覆盖索引(查询使用了索引并且需要返回的列在该索引中已经全部能够找到)减少 select *。 Extra字段值的含义 using index condition: 查找使用了索引但是需要回表查询数据。using where; using index: 查找使用了索引但是需要的数据都在索引列中能找到所以不需要回表查询数据。 前缀索引 当字段类型为字符串(varchar、text)时有时候需要索引很长的字符串这会让索引变得很大查询时浪费大量的磁盘IO影响查询效率。此时可以只将字符串的一部分前缀建立索引这样可以大大节约索引空间从而提高索引效率。 -- 创建前缀索引的语法 create index idx_xxxx on table_name(column(n));前缀长度可以根据索引的选择性来决定而选择性是指不重复的索引值(基数)和数据表的记录总数的比值索引选择性越高则查询效率越高唯一索引的选择性是1这是最好的索引选择性性能也是最好的。 select count(distinct email) / count(*) from user; select count(distinct substring(email, 1, 5))/count(*) from user;单列索引和联合索引 在业务场景中如果存在多个查询条件考虑针对于查询字段建立索引时建议建立联合索引而非单列索引。 多条件联合查询时MySQL 优化器会评估哪个字段的索引效率更高会选择该索引完成本次查询。 2.2.7 索引设计原则 索引的设计原则: 针对数据量较大且查询比较频繁的表建立索引。针对常作为查询条件(where)、排序(order by)、分组(group by) 操作的字段建立索引。尽量选择区分度高的列作为索引尽量建立唯一索引区分度越高使用索引的效率越高。如果是字符串类型的字段字段的长度越长可以针对字段的特点建立前缀索引。尽量使用联合索引减少单列索引查询时联合索引很多时候可以覆盖索引节省存储空间避免回表提高查询效率。要控制索引数量索引并不是多多益善索引越多维护索引结构的代价也就越大会影响增删改的效率。如果索引列不能存储 NULL 值请在创建表时使用 NOT NULL 约束它。当优化器知道每列是否包含 NULL 值时它可以更好地确定哪个索引最有效地用于查询。 2.3 SQL 优化 2.3.1 插入数据 insert 优化: -- 1. 批量插入 insert into user values(1, tom),(2, cat),(3, jerry); -- 2. 手动事务提交 start transaction; insert into user values(1, tom),(2, cat),(3, jerry); insert into user values(4, tom1),(5, cat1),(6, jerry1); commit; -- 3.主键顺序插入 主键顺序插入性能高于乱序插入。 -- 主键乱序插入819232767 -- 主键顺序插入12396581主键顺序插入性能高于乱序插入。 大批量插入数据 如果一次性需要插入大批量数据使用 insert 语句插入性能较低此时可以使用 MySQL 数据库提供的 load 指令进行插入。 sql.log 示例 1,tom 2,cat 3,jerry 4,tom1 5,cat1 6,jerry1# 客户端连接服务端时加上参数 --local-infile mysql --local-infile -u root -p # 设置全局参数 local_infile 为1开启从本地加载文件导入数据的开关 set global local_infile 1; # 切换到数据库 use databaseName; # 执行 load 指令将准备好的数据加载到表结构中。 load data local infile /root/sql.log into table user fields terminated by , lines terminated by \n; 2.3.2 主键优化 数据的组织方式 在 InnoDB 存储引擎中表数据都是根据主键顺序组织存放的这种存储方式的表称为索引组织表 (index organized table, 简称 IOT)。 页分裂 页可以为空也可以填充一半也可以填充 100%。每个页包含了 2-N 行数据(如果一行数据过大会行溢出)根据主键排列。 主键乱序插入会导致页分裂。 页合并 当删除一行数据时实际上记录并没有被物理删除只是记录被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。 当页中删除的记录达到 MERGE_THRESHOLD (默认页的 50%)InnoDB 会开始寻找最靠近的页(前或后)看看是否可以将两个页合并以优化空间使用。 MERGE_THRESHOLD合并页的阀值可以自己设置在创建表或者创建索引时指定。 主键的设计原则: 满足业务需求的情况下尽量降低主键的长度。插入数据时尽量选择顺序插入选择使用 AUTO_INCREMENT 自增主键。尽量不要使用 UUID 做主键或者是其他自然主键如身份证号。业务操作时避免对主键的修改。 2.3.3 order by 优化 排序的类型: Using filesort通过表的索引或全表扫描读取满足条件的数据行然后在排序缓冲区 sort buffer 中完成排序操作所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。Using index通过有序索引顺序扫描直接返回有序数据这种情况即为 using index不需要额外排序操作效率高。 -- 根据 age, phone 进行排序一个升序一个降序 explain select id, age, phone from user order by age asc, phone desc; -- 创建索引 指定排序的索引优化 create index idx_user_age_phone on user(age asc, phone desc);order by 优化的点: 根据排序字段建立合适的索引多字段排序时也遵循最左前缀法则。尽量使用覆盖索引.多字段排序一个升序一个降序此时需要注意联合索引在创建时的规则(asc/desc).如果不可避免的出现 filesort, 大数据量排序时可以适当增大排序缓冲区大小 sort_buffer_size (默认 256k). 2.3.4 group by 优化 在分组操作时可以通过索引来提高效率。分组操作时索引的使用也是满足最左前缀法则的。 2.3.5 limit 优化 一个常见又非常头疼的问题就是 limit 2000000,10, 此时需要 MySQL 排序前 2000010 记录仅仅返回 2000000 - 2000010 的记录其他记录丢弃查询排序的代价非常大。 优化思路一般分页查询时通过创建覆盖索引能够比较好地提高性能可以通过覆盖索引加子查询的形式进行优化。 explain select * from tb_sku t, (select id from tb_sku order by id limit 2000000, 10) a where t.id a.id;2.3.6 count 优化 count() 是一个聚合函数对于返回的结果集一行行的判断如果count函数的参数不是 null累计值就加 1否则不加最后返回累计值。 explain select count(*) from tb_user;MyISAM 引擎把一个表的总行数存在了磁盘上因此执行 count(*) 的时候会直接返回这个数效率很高。(只有满足没有 where 条件时才会直接返回总记录数)InnoDB 引擎就麻烦了它执行 count(*) 的时候需要把数据一行一行地从引擎里面读出来然后累积计数。 优化思路自己计数。可以使用内存型数据库存储表的记录数如 redis count的几种用法: count(*)InnoDB 引擎并不会把全部字段取出来而是专门做了优化不取值服务层直接按行进行累加。count(主键): InnoDB 引擎会遍历整张表把每一行的 主键id 值取出来返回给服务层。服务层拿到主键后直接按行进行累加(主键不可能为null)。count(字段): 没有 not null 约束InnoDB 引擎会遍历整张表把每一行的字段值都取出来返回给服务层服务层判断是否为 null不为 null计数累加。有 not null 约束InnoDB 引擎会遍历整张表把每一行的字段值都取出来返回给服务层直接按行进行累加。 count(1)InnoDB 引擎会遍历整张表但不取值。服务层对于返回的每一行放一个数字 1 进去直接按行进行累加。 按照效率排序的话 count(字段) count(主键id) count(1) ≈ \approx ≈ count(*)。所以尽量使用 count(*); 2.3.7 update 优化 InnoDB 的行锁是针对索引加的锁不是针对记录加的锁并且该索引不能失效否则会从行级锁升级为表锁。 2.4 视图/存储过程/触发器 2.4.1 视图 视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在行和列数据来自定义视图的查询中使用的表并且是在使用视图时动态生成的。 通俗的讲视图只保存了查询的SQL逻辑不保存查询结果。所以我们在创建视图的时候主要的工作就落在创建这条SQL查询语句上。 语法: -- 创建视图 create [or replace] view 视图名称[(列名列表)] as select语句 [with [cascaded | local ] check option] -- 查询 -- 1. 查看创建视图的语句 show create view 视图名称; -- 2. 查看视图的数据 select * from 视图名称...; -- 修改 -- 方式一 create [or replace] view 视图名称[(列名列表)] as select语句 [with [cascaded | local ] check option] -- 方式二 alter view 视图名称[(列名列表)] as select语句 [with [cascaded | local] check option] -- 删除 drop view [if exists] 视图名称 [,视图名称]...视图的检查选项: 当使用 with check option 子句创建视图时MySQL 会通过视图检查正在更改的每个行例如 插入、更新、删除以使其符合视图的定义。MySQL 允许基于另一个视图创建视图它还会检查依赖视图中的规则以保持一致性。为了确定检查范围mysql 提供了两个选项cascaded 和 local默认值为 cascaded。 视图的更新: 要使视图可更新视图中的行与基础表中的行之间必须存在一对一的关系。如果视图包含以下任何一项则该视图不可更新 聚合函数或窗口函数 (sum()、min()、max()、count()等)DISTINCTGROUP BYHAVINGUNION 或者 UNION ALL 视图作用: 简单视图不仅可以简化用户对数据的理解也可以简化他们的操作。那些被经常使用的查询可以被定义为视图从而使得用户不必为以后的操作每次指定全部的条件。安全数据库可以授权但不能授权到数据库特定的行和特定的列上。通过视图用户只能查询和修改他们所能见到的数据。数据独立视图可帮助用户屏蔽真实表结构变化带来的影响。 2.4.2 存储过程 2.4.2.1 存储过程介绍 存储过程是事先经过编译并存储在数据库中的一段 SQL 语句的集合调用存储过程可以简化应用开发人员的很多工作减少数据在数据库和应用服务器之间的传输对于提高数据处理的效率是有好处的。 存储过程思想上很简单就是数据库 SQL 语言层面的代码封装与重用。 2.4.2.2 存储过程的特点 封装、复用可以接收参数、也可以返回数据减少网络交互效率提升 2.4.2.3 存储过程的语法 -- 创建 create procedure 存储过程名称([参数列表]) begin -- sql 语句 end; -- 调用 call 名称([参数]) -- 查看 -- 查询指定数据库 xxx 中的存储过程及状态信息 select * from information_schema.routines where routine_schemaxxx; -- 查询某个存储过程的定义 show create procedure 存储过程名称; -- 删除 drop procedure [if exists] 存储过程名称;在命令行中执行创建存储过程的 sql 时需要通过关键字 delimiter 指定 sql 语句的结束符。 2.4.2.4 存储过程的变量 系统变量是 MySQL 服务器提供的不是用户定义的属于服务器层面。分为全局变量(GLOBAL)会话变量(SESSION)。用户定义变量是用户根据需要自己定义的变量用户变量不用提前声明在用的时候直接用 “变量名” 使用就可以。其作用域为当前连接。局部变量是根据需要定义的在局部生效的变量访问之前需要 Declare 声明。可用作存储过程内的局部变量和输入参数局部变量的范围是在其内声明的 BEGIN … END 块。 查看系统变量 -- 查看所有系统变量 show [session | global] variables; -- 可以通过like模糊匹配方式查找变量 show [session | global] variables like xx; -- 查看指定变量的值 select [session | global] 系统变量名;设置系统变量 set [session | global] 系统变量名值; set [session | global]系统变量名值;如果没有指定 session/global 默认是 session会话变量 mysql 服务重新启动后所设置的全局参数就会失效要想不失效可以在 /etc/my.cnf 中配置 赋值用户定义变量 set var_name expr [,var_name expr]...; set var_name:expr [,var_name : expr]...;select var_name : expr [,var_name : expr]...; select 字段名 into var_name from 表名;使用用户定义变量 select var_name;用户定义的变量无需对其进行声明或初始化只不过获取到的值为 null。 声明 declare 变量名 变量类型[default ...];变量类型是数据库字段类型int、bigint、char、varchar、date、time 等 赋值 set 变量名 值; set 变量名 : 值; select 字段名 into 变量名 from 表名;2.4.2.5 存储过程的IF if 语法 if 条件1: then ... -- 可选 ELSEIF 条件2then ... -- 可选 else ... end if;2.4.2.6 存储过程的参数 类型含义备注IN该类参数作为输入也就是需要调用时传入值默认out该类参数作为输出也就是该参数可以作为返回值inout即可以作为输入参数也可以作为输出参数 用法 create procedure 存储过程名称([in/out/inout 参数名 参数类型]) begin -- sql语句 end;2.4.2.7 存储过程的case 语法一 case case_valuewhen when_value1 then statement_list1[when when_value2 then statement_list2]..,[else statement_list] end case;语法二 case when search_condition1 then statement_list1[when search_condition2 then statement_list2][else statement_list] end case;2.4.2.8 存储过程的循环 while 循环有条件的循环控制语句。满足条件后再执行循环体中的 sql。 -- 先判断逻辑如果条件为 true,则执行逻辑否则,不执行逻辑。 while 条件 DO -- sql 逻辑 end while;repeat 循环是有条件的循环控制语句当满足条件的时候退出循环。 -- 先执行一次逻辑然后判定逻辑是否满足如果满足则退出如果不满足则继续下一次循环。 repeat sql 逻辑until 条件 end repeat;loop 循环实现简单的循环如果不在 sql 逻辑中增加退出循环的条件可以用其来实现简单的死循环。loop 可以配合以下两个语句使用 leave: 配合循环使用退出循环iterate必须用在循环中作用是跳过当前循环剩下的语句直接进入下一次循环。 [begin_label:] loopsql 逻辑 end loop [end label];-- 退出指定标记的循环体 leave label; -- 直接进入下一次的循环 iterate label;2.4.2.9 存储过程的游标 游标 (cursor) 是用来存储查询结果集的数据类型在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、open、fetch 和 close。 声明游标 declare 游标名称 cursor for 查询语句;打开游标 open 游标名称;获取游标记录 fetch 游标名称 into 变量[,变量];关闭游标 close 游标名称;2.4.2.10 存储过程的条件处理程序 条件处理程序 (handler) 可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。 declare handler_action handler for condition_value [,condition_value]... statement;handler_action continue: 继续执行当前程序exit: 终止执行当前程序 condition_value sqlstate sqlstate_value: 状态码如 02000sqlwarning: 所有以 01 开头的 sqlstate 代码的简写not found: 所有以 02 开头的 sqlstate 代码的简写sqlexception所有没有被 sqlwarning 或 not found 捕获的 sqlstate 代码的简写。 2.4.3 存储函数 存储函数是有返回值的存储过程存储函数的参数只能是 in 类型的。 create function 存储函数名称([参数列表]) returns type [characteristic ...] begin-- sql 语句return ...; end;characteristic 说明 deterministic相同的输入参数总是产生相同的结果no sql不包含 sql 语句reads sql data: 包含读取数据的语句但不包含写入数据的语句。 2.4.4 触发器 触发器是表有关的数据库对象指在 insert/update/delete 之前或之后触发并执行触发器中定义的 SQL 语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性日志记录数据校验等操作。 使用别名 old 和 new 来引用触发器中发生变化的记录内容这与其他数据库是相似的。现在触发器还支持行级触发不支持语句级出发。 触发器类型new 和 oldinsert 型触发器new 表示将要或者已经新增的数据update 型触发器old 表示修改之前的数据new 表示将要或已经修改后的数据delete 型触发器old 表示将要或者已经删除的数据 创建触发器 create trigger trigger_name before/after insert/update/delete on tbl_name for each row -- 行级触发器 begintrigger_stmt; end;查看触发器 show triggers;删除触发器 -- 如果没有指定 schema_name,默认为当前数据库。 drop trigger [schema_name] trigger_name;2.5 锁 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中除传统的计算资源 (cpu、ram、i/o) 的争用外数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说锁对数据库而言显得尤其重要也更复杂。 MySQL 中的锁按照锁的粒度分为以下三类 全局锁锁定数据库中的所有表表级锁每次操作锁住整张表行级锁每次操作锁住对应的行数据 2.5.1 全局锁 全局锁就是对整个数据库实例加锁加锁后整个实例就处于只读状态后续的 DML 的写语句DDL 语句以及更新操作的事务提交语句都将被阻塞。 其典型的使用场景是做全库的逻辑备份对所有的表进行锁定从而获取一致性视图保证数据的完整性。 -- 加全局锁 flush tables with read lock; -- 数据库备份 mysqldump -uroot -p123456 dbname dbname.sql -- 解锁 unlock tables;数据库中加全局锁是一个比较重的操作存在以下问题 如果在主库上备份那么在备份期间都不能执行更新业务基本上就得停摆。如果在从库上备份那么在备份期间从库不能执行主库同步过来的二进制日志 (binlog)会导致主从延迟。 在 innoDB 引擎中我们可以在备份时加上参数 --single-transaction 参数来完成不加锁的一致性数据备份。 # 通过快照 mysqldump --single-transaction -uroot -p123456 dbname dbname.sql2.5.2 表级锁 表级锁每次操作锁住整张表。锁定粒度大发生锁冲突的概率最高并发度最低。应用在 MyISAM、InnoDB、BDB等存储引擎中。 对于表级锁主要分为以下三类 表锁元数据锁 (meta data lock, MDL)意向锁 2.5.2.1 表锁 对于表锁分为两类 表共享读锁(read lock)会阻塞写不会阻塞读表独占写锁(write lock)会阻塞其他客户端的读和写。 -- 加锁 lock tables 表名... read/write; --解锁 unlock tables; -- 或者客户端断开连接读锁不会阻塞其他客户端的读但是会阻塞写。写锁既会阻塞其他客户端的读又会阻塞其他客户端的写。 2.5.2.2 元数据锁 元数据锁 (meta data lockMDL): 加锁的过程是系统自动控制无需显式使用在访问一张表的时候会自动加上。元数据锁主要作用是维护表元数据的数据一致性在表上有活动事务的时候不可以对元数据进行写入操作。 为了避免 DML 与 DDL 冲突保证读写的正确性。 在 MySQL 5.5 中引入了 MDL, 当对一张表进行增删改查的时候加 MDL 读锁(共享)当对表结构进行变更操作时加 MDL 写锁(排他)。 对应 SQL锁类型说明lock tables xxx read/writeshared_read_only/shared_no_read_writeselect、select … lock in modeshared_read与 shared_read、shared_write兼容与 exclusive 互斥insert、update、delete、select … for updateshared_write与 shared_read、shared_write兼容与 exclusive 互斥alter table …exclusive与其他的 MDL 互斥 -- 查看元数据锁 select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;2.5.2.3 意向锁 为了避免 DML 在执行时加的行锁和表锁的冲突在 InnoDB 中引入了意向锁使得表锁不用检查每行数据是否加锁使用意向锁来减少表锁的检查。 意向锁的类型 意向共享锁 (IS): 由语句 select … lock in share mode 添加。意向排他锁 (IX): 由 insert、update、delete、select … for update 添加。 意向锁和表锁的兼容情况 意向共享锁 (IS): 与表锁共享锁 (read) 兼容与表锁排它锁 (write) 互斥意向排他锁 (IX): 与表锁共享锁 (read) 及排它锁 (write) 都互斥。意向锁之间不会互斥。 -- 查看意向锁及行锁的加锁情况 select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.data_locks;2.5.3 行级锁 行级锁每次操作锁住对应的行数据。锁定粒度最小发生锁冲突的概率最低并发度最高。应用在 InnoDB 存储引擎中。 InnoDB 的数据是基于索引组织的行锁是通过对索引上的索引项加锁来实现的而不是对记录加的锁。对于行级锁主要分为以下三类 行锁(record lock)锁定单个行记录的锁防止其他事务对此进行 update 和 delete。在 RC、RR 隔离级别下都支持。间隙锁 (Gap lock)锁定索引记录间隙(不含该记录)确保索引记录不变防止其他事务在这个间隙进行 insert产生幻读。在 RR 隔离级别下都支持。临键锁 (next-key lock): 行锁和间隙锁的组合同时锁住数据并锁住数据前面的间隙 Gap。在 RR 隔离级别下支持。 2.5.3.1 行锁 InnoDB 实现了以下两种类型的行锁 共享锁 (S): 允许一个事务去读一行阻止其他事务获得相同数据集的排它锁。排他锁 (X)允许获取排他锁的事务更新数据阻止其他事务获得相同数据集的共享锁和排他锁。 SQL行锁类型说明insert …排他锁自动加锁update …排他锁自动加锁delete …排他锁自动加锁select (正常)不加任何锁select … lock in share mode共享锁需要手动在 select 之后加 lock in share modeselect … for update排他锁需要手动在 select 之后加 for update 默认情况下InnoDB 在 repeatable read 事务隔离级别运行InnoDB 使用 next-key 锁进行搜索和索引扫描以防止幻读。 针对唯一索引进行检索时对已存在的记录进行等值匹配时将会自动优化为行锁。InnoDB 的行锁是针对于索引加的锁不通过索引条件检索数据那么 InnoDB 将对表中的所有记录加锁此时就会升级为表锁。 2.5.3.2 间隙锁/临键锁 默认情况下InnoDB 在 repeatable read 事务隔离级别运行InnoDB 使用 next-key 锁进行搜索和索引扫描以防止幻读。 索引上的等值查询(唯一索引), 给不存在的记录加锁时优化为间隙锁。索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时next-key lock 退化为 间隙锁。索引上的范围查询(唯一索引)会访问到不满足条件的第一个值为止。 间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。 2.6 InnoDB 引擎 2.6.1 逻辑存储结构 2.6.2 架构 MySQL 5.5 版本开始默认使用 InnoDB 存储引擎它擅长事务处理具有奔溃恢复特性在日常开发中使用非常广泛。下面是 InnoDB 架构图左侧为 内存结构右侧为磁盘结构。 2.6.2.1 内存架构 Buffer pool: 缓冲池是主内存中的一个区域里面可以缓存磁盘上经常操作的真实数据在执行增删改查操作时先操作缓冲池中的数据(若缓冲池没有数据则从磁盘中加载并缓存)然后再以一定频率刷新到磁盘从而减少磁盘 IO加快处理速度。 缓冲池以 page 页为单位底层采用链表数据结构管理page。根据状态将 page 分为三种类型 free page: 空闲page,未被使用。clean page: 被使用page,数据没有被修改过。dirty page: 脏页被使用page,数据被修改过页中数据与磁盘的数据产生了不一致。 Change Buffer更改缓冲区(针对于非唯一二级索引页)在执行 DML 语句时如果这些数据 Page 没有在 Buffer Pool 中不会直接操作磁盘而会将数据变更存在更改缓冲区 Change Buffer 中在未来数据被读取时再将数据合并恢复到 Buffer pool 中再将合并后的数据刷新到磁盘中。 Change Buffer 的意义是什么 与聚集索引不同二级索引通常是非唯一的并且以相对随机的顺序插入二级索引。同样删除和更新可能会影响索引树中不相邻的二级索引页如果每一次都操作磁盘会造成大量的磁盘IO。有了Change Buffer 之后我们可以在缓冲池中进行合并处理减少磁盘IO。 Adaptive Hash Index: 自适应 hash 索引用于优化对 Buffer Pool 数据的查询。InnoDB 存储引擎会监控对表上各索引页的查询如果观察到hash索引可以提升速度则建立hash索引称之为自适应hash索引。 自适应哈希索引无需人工干预是系统根据情况自动完成的。 参数adaptive_hash_index Log Buffer: 日志缓冲区用来保存要写入磁盘中的log日志数据(redo log、undo log)默认大小为 16 MB日志缓冲区的日志会定期刷新到磁盘中如果需要更新、插入或删除多行的事务增加日志缓冲区的大小可以节省磁盘I/O。 参数 innodb_log_buffer_size: 缓冲区大小innodb_flush_log_at_trx_commit: 日志刷新到磁盘时机。 1日志在每次事务提交时写入并刷新到磁盘0每秒将日志写入并刷新到磁盘一次2日志在每次事务提交后写入并每秒刷新到磁盘一次。 2.6.2.2 磁盘架构 System Tablespace: 系统表空间是更改缓冲区的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建它也肯能包含表和索引数据。(在 MySQL 5.X 版本中还包含 InnoDB 数据字典、undolog 等) 参数 innodb_data_file_path File-Per-Table Tablespaces每个表的文件表空间包含单个 InnoDB 表的数据和索引并存储在文件系统上的单个数据文件中。 参数innodb_file_per_table General Tablespaces: 通用表空间需要通过 create tablespace 语法创建通用表空间在创建表时可以指定该表空间。 -- 创建表空间 create tablespace xxx add datafile filename。ibd enginengin_name;Undo Tablespaces: 撤销表空间MySQL 实例在初始化时会自动创建两个默认的 undo 表空间(初始大小 16 M)用于存储 undo log 日志。 Temporary TablespacesInnoDB 使用会话临时表空间和全部临时表空间。存储用户创建的临时表等数据。 Doublewrite Buffer Files双写缓冲区innoDB 引擎将数据页从 Buffer Pool 刷新到磁盘前先将数据页写入双写缓冲区文件中便于系统异常时恢复数据。 双写缓冲区文件 #ib_16384_0.dblwr #ib_16384_1.dblwr Redo log: 重做日志是用来实现事务的持久性。该日志文件由两部分组成重做日志缓冲区(redo log buffer)以及重做日志文件 (redo log),前者是在内存中后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中用于在刷新脏页到磁盘时发生错误时进行数据恢复使用。 以循环的方式写入重做日志文件涉及两个文件 ib_logfile0ib_logfile1 2.6.2.3 架构-后台线程 Master Thread核心后台线程负责调度其他线程还负责将缓冲池中的数据异步刷新到磁盘中保持数据的一致性。还包括脏页的刷新、合并插入缓冲、undo 页的回收。IO Thread在InnoDB存储引擎中大量使用了AIO来处理IO请求这样可以极大地提高数据库的性能而 IO Thread 主要负责这些 IO 请求的回调。 Read thread默认个数 4负责读操作Write thread默认个数 4负责写操作log thread默认个数 1负责将日志缓冲区刷新到磁盘insert buffer thread默认个数 1,负责将写缓冲区内容刷新到磁盘。 Purge Thread主要用于回收事务已经提交了的 undo log, 在事务提交之后undo log 可能不用了就用它来回收。Page Cleaner Thread: 协助Master Thread 刷新脏页到磁盘的线程它可以减轻 Master Thread 的工作压力减少阻塞。 2.6.3 事务原理 2.6.3.1 redo log redo log 重做日志记录的是事务提交时数据页的物理修改是用来实现事务的持久性。 该日志文件由两部分组成重做日志缓冲(redo log buffer) 以及 重做日志文件 (redo log file), 前者是在内存中后者是在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中用于在刷新脏页到磁盘发生错误时进行数据恢复使用。 2.6.3.2 undo log undo log 回滚日志用于记录数据被修改前的信息作用包含两个提供回滚 和 MVCC(多版本并发控制)。 undo log 和 redo log 记录物理日志不一样它是逻辑日志。可以认为当 delete 一条记录时undo log 中会记录一条对应的 insert 记录反之亦然当 update 一条记录时它记录一条对应相反的 update 记录。当执行 rollback 时就可以从 undo log 中的逻辑记录读取到相应的内容并进行回滚。 undo log 销毁时: undo log 在事务执行时产生事务提交时并不会立即删除 undo log因为这些日志可能还用于 MVCC。 Undo log存储undo log 采用段的方式进行管理和记录存放在前面介绍的rollback segment 回滚段中内部包含 1024 个undo log segment。 2.6.4 MVCC 2.6.4.1 MVCC 基本概念 当前读读取的是记录的最新版本读取时还要保证其他并发事务不能修改当前记录会对读取的记录进行加锁。对于我们日常操作如 select … lock in share mode(共享锁)select … for uodate、update、insert、delete(排他锁)都是一种当前读。 快照读简单的 select (不加锁) 就是快照读快照读读取的记录数据的可见版本有可能是历史数据不加锁是非阻塞读。 Read Committed: 每次 select都生成一个快照读。Repeatable Read开启事务后第一个 select 语句才是快照读的地方。Serializable快照读会退化为当前读。 MVCC全称 Multi-Version Concurrency Control, 多版本并发控制。指维护一个数据库的多个版本使得读写操作没有冲突快照读为 MySQL 实现 MVCC 提供了一个非阻塞读功能。MVCC 的具体实现还需要依赖于数据库记录中的三个隐式字段、undo log日志、readview。 2.6.4.2 记录中的隐藏字段 DB_TRX_ID: 最近修改事务ID记录这条记录或最后一次修改该记录的事务ID。DN_ROLL_PTR: 回滚指针指向这条记录的上一个版本用于配合 undo log指向上一个版本。DB_ROW_ID: 隐藏主键如果表结构没有指定主键将会生成该隐藏字段。 2.6.4.3 Undo Log Undo Log 回滚日志在 insert、update、delete 的时候产生的便于数据回滚的日志。 当 insert 的时候产生的 undo log 日志只在回滚时需要在事务提交后可被立即删除。 而 update、delete 的时候产生的 undo log 日志不仅在回滚时需要在快照读时也需要不会立即被删除。 undo log 版本链不同事务或相同事务对同一条记录进行修改会导致该记录的 undo log 生成一条记录版本链表链表的头部是最新的旧记录链表尾部是最早的旧纪录。 2.6.4.3 Readview Readview (读视图) 是快照读 SQL 执行时 MVCC 提取数据的依据记录并维护系统当前活跃的事务(未提交的)id。 Readview 中包含了四个核心字段 m_ids: 当前活跃的事务id集合min_trx_id: 最小活跃事务idmax_trx_id: 预分配事务id, 当前最大事务id 1 (因为事务id是自增的)creator_trx_id: ReadView 创建者的事务id 版本链数据访问规则trx_id 代表当前事务id trx_id creator_trx_id ? 可以访问该版本 成立说明数据是当前这个事务更改的。trx_id min_trx_id ? 可以访问该版本 成立说明数据已经提交。trx_id max_trx_id ? 不可以访问该版本 成立说明该事务是在ReadView生成后才开启的。min_trx_id trx_id max_trx_id ? 如果 trx_id 不在 m_ids 中是可以访问该版本的。 成立说明数据已经提交。 不同的隔离级别生成 ReadView 的时机不同 Read Committed: 在事务中每一次执行快照读时生成 ReadView。Repeatable Read仅在事务中第一次执行快照读时生成 ReadView后面复用该 ReadView。 2.7 MySQL 管理 2.7.1 系统数据库 MySQL 数据库安装完成后自带了以下四个数据库具体作用如下 mysql: 存储MySQL服务器正常运行所需要的各种信息 (时区、主从、用户、权限等)information_schema: 提供了访问数据库元数据的各种表和视图包含数据库、表、字段类型及访问权限等。performance_schema: 为 MySQL 服务器运行时状态提供了一个底层监控功能主要用于收集数据库服务器性能参数。sys: 包含了一系列方便 DBA 和开发人员利用 performance_schema 性能数据库进行性能调优和诊断的视图。 2.7.2 常用工具 mysqlmysqladminmysqlbinlogmysqlshowmysqldumpmysqlimport/source 3. MySQL 运维篇 3.1 日志 日志分类 错误日志二进制日志查询日志慢查询日志 3.1.1 错误日志 错误日志它记录了当 mysqld 启动和停止时以及服务器在运行过程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时建议首先查看此日志。 该日志是默认开启的默认存放目录 /var/log/默认的日志文件名为 mysqld.log。查看日志位置 show variables like %log_error%;3.1.2 二进制日志 二进制日志 (BINLOG) 记录了所有的 DDL (数据定义语言) 语句 和 DML (数据操纵语言) 语句但不包括数据查询 (select、show) 语句。 作用 灾难时的数据恢复MySQL 的主从复制。 在MySQL8版本中默认二进制日志是开启的。 show variables like %log_bin%;日志格式 STATEMENT基于 SQL 语句的日志记录对数据进行修改的SQL都会记录在日志文件中。ROW基于行的日志记录记录的是每一行的数据变更。(默认)MIXED混合了 STATEMENT 和 ROW 两种格式默认采用 STATEMENT在某些特殊情况下会自动切换为 ROW 进行记录。 show variables like %binlog_format%;日志查看由于日志是以二进制方式存储的不能直接读取需要通过二进制日志查询工具 mysqlbinlog 来查看。 mysqlbinlog [参数选项] logfilename # -d 指数据库名称只列出指定的数据库相关操作; -o 忽略掉日志中的前n行命令; -v 将行事件(数据变更)重构为SQL语句; -w 将行事件(数据变更)重构为SQL语句并输出注释信息;日志删除对于比较繁忙的业务系统每天生成的binlog数据巨大如果长时间不清楚将会占用大量磁盘空间。 reset master删除全部的 binlog 日志删除之后日志编号将从 binlog.000001 重新开始。purge master logs to ‘binlog.xxx’删除 xxx 编号之前的所有日志。purge master logs before ‘yyyy-mm-dd hh24:mi:ss’删除日志为 ‘yyyy-mm-dd hh24:mi:ss’ 之前产生的所有日志。 也可以在 mysql 的配置文件中配置二进制日志的过期时间设置了之后二进制日志过期会自动删除。 show variables like %binlog_expire_logs_seconds%;3.1.3 查询日志 查询日志中记录了客户端的所有操作语句而二进制日志不包含查询数据的SQL语句。默认情况下查询日志是未开启的。 show variables like general;# 该选项用来开启查询日志可选值 0 关闭1 开启 general_log 1 # 设置日志的文件名如果没有指定默认的文件名未 host_name.log general_log_file mysql_query.log3.1.4 慢查询日志 慢查询日志记录了所有执行时间超过参数 long_query_time 设置值并且扫描记录数不小于 min_examined_row_limit 的所有的 SQL 语句的日志默认未开启。long_query_time 默认为 10 秒最小为 0,精度可以到微妙。 #慢查询日志开启 slow_query_log 1 #执行时间参数 long_query_time 2默认情况下不会记录管理语句也不会记录不使用索引进行查找的查询。 #记录执行较慢的管理语句 log_slow_admin_statements1 #记录执行较慢的未使用索引的语句 log_queries_not_indexes1 3.2 主从复制 3.2.1 主从复制概述 主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中然后在从库上对这些日志重新执行(也叫重做)从而使得从库和主库的数据保持同步。 MySQL 支持一台主库同时向多台从库进行复制从库同时也可以作为其他从服务器的主库实现链状复制。 MySQL 复制的优点主要包含以下三个方面 主库出现问题可以快速切换到从库提供服务。实现读写分离降低主库的访问压力。可以在从库中执行备份以避免备份期间影响主库服务。 3.2.2 主从复制原理 **1. Master 主库在事务提交时会把数据变更记录在二进制日志文件 Binlog 中。 2. 从库读取主库的二进制日志文件 Binlog写入到从库的中继日志 Relay log。 3. slave 重做中继日志中的事件将改变反映它自己的数据。 3.2.3 主从复制搭建 准备两台服务器。分别安装MySQL完成初始化。 Centos中MySQL安装教程(打开教程后直接跳到安装MySQL的部分) 5.0 版本需要手动开启 binlog # my.cnf 添加 log_binON# 开放指定的3306端口号 或者 关闭服务器的防火墙 firewall-cmd --zonepublic --add-port3306/tcp -permanent firewall-cmd -reload# 或者 systemctl stop firewalld systemctl disable firewalld主库配置 # 1. 修改配置文件 /etc/my.cnf # mysql 服务id,保证整个集群环境中唯一取值范围1-2^32-1默认1。 server-id1 # 是否只读1代表只读0代表读写 read-only0 # 忽略的数据指不需要同步的数据库 #binlog-ignore-dbmysql # 指定同步的数据库 #binlog-do-dbdb01#2. 重启Mysql 服务 systemctl restart mysqld-- 3. 登录 mysql创建远程连接的账号并授予主从复制的权限 -- 创建 mstest 用户并设置密码该用户可在任意主机连接该 MySQL 服务。 create user mstest% identified with mysql_native_password by Gjw%123456; -- 为 mstest% 用户分配主从复制权限 grant replication slave on *.* to mstest%; -- 4.通过指令查看二进制日志的坐标 -- 字段含义, file 从哪个日志文件开始推送日志文件position 从哪个位置开始推送日志binlog_ignore_db 指定不需要同步的数据库。 show master status;从库配置 # 1. 修改配置文件 /etc/my.cnf # mysql 服务id,保证整个集群环境中唯一取值范围1-2^32-1默认1。 server-id2 # 是否只读1代表只读0代表读写 read-only1 # 超级用户也是只读 #super-read-only1#2. 重启Mysql 服务 systemctl restart mysqld-- 3. 登录 mysql设置主库配置 -- mysql 版本是 8.0.23 中语法如下 change replication source to source_hostxxx,source_userxxx,source_passwordxxx,source_log_filexxx,source_log_posxxx; -- mysql 版本是 8.0.23之前的版本语法如下 change master to master_hostxxx,master_userxxx,master_passwordxxx,master_log_filexxx,master_log_posxxx; -- 4. 开启同步操作 -- 8.0.22 之后的语法 start replica; -- 8.0.22 之前的语法 start slave; -- 5. 查看主从同步状态 -- 8.0.22 之后的语法 show replica status; -- 8.0.22 之前的语法 show slave status;3.3 分库分表 3.3.1 介绍 随着互联网及移动互联网的发展应用系统的数据量也是成指数式增长的若采用单数据库进行数据存储存在以下性能瓶颈 IO瓶颈热点数据太多数据库缓存不足产生大量磁盘IO效率较低。请求数据太多带宽不够网络IO瓶颈。CPU瓶颈排序、分组、连接查询、聚合统计等SQL会耗费大量的CPU资源请求数太多CPU出现瓶颈。 分库分表的中心思想都是将数据分散存储使得单一数据库/表的数据量变小来缓解单一数据库性能的问题从而达到提升数据库性能的目的。 3.3.1.1 拆分策略 垂直拆分 垂直分库垂直分表 水平拆分 水平分库水平分表 3.3.1.1.1 垂直拆分 垂直分库以表为依据根据业务将不同表拆分到不同库。 垂直分库的特点 每个库的表结构都不一样。每个库的数据也不一样。所有库的数据是全量数据。 垂直分表以字段为依据根据字段属性将不同字段拆分到不同表种。 垂直分表的特点 每个表的结构都不一样。每个表的数据也不一样一般通过一列(主键/外键) 关联。所有表的并集是全量数据。 3.3.1.1.2 水平拆分 水平分库以字段为依据按照一定策略将一个库的数据拆分到多个库中。 水平分库的特点 每个库的表结构都一样。每个库的数据都不一样。所有库的并集是全量数据。 水平分表以字段为依据按照一定策略将一个表的数据拆分到多个表中。 水平分表的特点 每个表的表结构都一样。每个表的数据都不一样。所有表的并集是全量数据。 3.3.1.2 实现技术 shareingJDBC基于 AOP 原理在应用程序中对本地执行的SQL进行拦截解析、改写、路由处理。需要自行编码配置实现只支持java语言性能较高。MyCat数据库分库分表中间件不用调整代码即可实现分库分表支持多种语言性能不及前者。 3.3.2 Mycat概述 Mycat 是开源的、活跃的、基于 Java 语言编写的 MySQL 数据库中间件。可以像使用 mysql 一样来使用 mycat对于开发人员来说根本感觉不到 mycat 的存在。 Mycat 优势 性能可靠稳定强大的技术团队体系完整社区活跃 Mycat 安装MyCat 支持 Windows 和 Linux 运行环境我们需要在准备好的服务器上安装如下软件。 MySQLJDKMycat 服务器安装软件说明server-1jdk、Mycat、MySQLMyCat中间件服务器、分片服务器server-2MySQL分片服务器server-3MySQL分片服务器 # 下载 MyCat Linux 版本在 centos7 安装 wget https://github.com/MyCATApache/Mycat-Server/releases/download/Mycat-server-1675-release/Mycat-server-1.6.7.5-release-20200422133810-linux.tar.gz # 解压 MyCat 压缩包到 /usr/local/ tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/MyCat 的架构 3.3.3 Mycat入门 需求 由于 tb_order 表中数据量很大磁盘IO及容量都到达了瓶颈现在需要对 tb_order 表进行数据分片分为三个数据节点每一个节点主机位于不同的服务器上具体结构。参考下图 环境准备 分片配置 schema.xml vim /usr/local/mycat/conf/schema.xml分片配置 server.xml : 启动服务 # 切换目录到 /usr/local/mycat/ cd /usr/local/mycat/ #启动 bin/mycat start #停止 bin/mycat stop #查看服务是否启动成功 tail -f wrapper.logMycat 启动之后占用端口号 8066; 分片测试 # 连接并登录 Mycat mysql -h 192.168.3.27 -P 8066 -u root -p1234563.3.4 Mycat配置 3.3.4.1 schema.xml schema.xml 作为 MyCat 中最重要的配置文件之一涵盖了 MyCat 的逻辑库、逻辑表、分片规则、分片节点及数据源的配置。 主要包含以下三组标签 schema 标签datanode 标签datahost 标签 schema 标签用于定义 MyCat 实例中的逻辑库一个 MyCat 实例可以有多个逻辑库可以通过 schema 标签来划分不同的逻辑库。 MyCat 中的逻辑库的概念等同于 MySQL 中的 database 概念需要操作某个逻辑库下的表时也需要切换逻辑库 (use xxx); schema核心属性 name: 指定自定义的逻辑库名大小写敏感checkSQLschema: 在 SQL 语句操作时指定了数据库名称执行时是否自动去除true 自动去除false 不自动去除sqlMaxLimit: 如果未指定 limit 进行查询列表查询模式查询多少条记录。 schema 标签(table): 定义了 MyCat 中逻辑库 schema 下的逻辑表所有需要拆分的表都需要在 table 标签中定义。 schema 下 table 核心属性 name: 定义逻辑表表名在该逻辑库下唯一大小写敏感dataNode: 定义逻辑表所属的dataNode,该属性需要与dataNode标签中name对应多个dataNode 逗号分割。rule: 分片规则的名字分片规则名字是在rule.xml中定义的primaryKey: 逻辑表对应真实表的主键type: 逻辑表的类型目前逻辑表只有全局表和普通表如果未配置就是普通表全局表配置为 global dataNode 标签 定义了 MyCat 中的数据节点也就是我们通常说的数据分片。一个 dataNode 标签就是一个独立的数据分片。 dataNode 核心属性 name: 定义数据节点的名称dataHost: 数据库实例主机名称引用自 dataHost 标签中的 name 属性。database: 定义分片所属数据库。 dataHost标签在 MyCat 逻辑库中作为底层标签存在直接定义了具体的数据库实例、读写分离、心跳语句。 dataHost 核心属性 name: 唯一标识供上层使用。maxConn/minConn: 最大连接数/最小连接数balance: 负载均衡策略取值 0、1、2、3writeType: 写操作分发方式(0: 写操作转发到第一个 writeHost第一个挂了切换到第二个1写操作随机分发到配置的 writeHost)dbDriver: 数据库驱动 native、jdbc 3.3.4.2 rule.xml rule.xml 中定义所有拆分表的规则在使用过程中可以灵活的使用分片算法或者对同一个分片算法使用不同的参数它让分片过程可配置化。主要包含两类标签 tableRule:Function: 3.3.4.3 server.xml server.xml 配置文件包含了 MyCat 的系统配置信息主要有两个重要的标签system、user 3.3.5 Mycat分片 3.3.5.1 垂直拆分 全局表配置对于省、市、区表是属于数据字典表在多个业务模块中都可能会遇到可以将其设置为全局表利于业务操作。 3.3.5.2 水平拆分 分片规则 范围根据指定字段及其配置的范围与数据节点的对应情况来决定该数据属于哪一个分片。autopartition-long取模根据指定字段值与节点数量进行求模运算根据运算结果来决定该数据属于哪一个分片。mod-long一致性hash: 相同的哈希因子计算总是被划分到相同的分区表中不会因为分区节点的增加而改变原来数据的分区位置。sharding-by-murmur枚举通过在配置文件中配置可能的枚举值指定数据分布到不同数据节点上本规则适用于按照省份、性别、状态拆分数据等业务。sharding-by-intfile应用指定运行阶段由应用自主决定路由到那个分片直接根据字符串子串(必须是数字)计算分片号。sharding-by-substring固定分片hash算法该算法类似于十进制的求模运算但是为二进制的操作例如取 id 的二进制低 10 位与 1111111111 进行位运算 sharding-by-long-hash字符串hash解析截取字符串中指定位置的子字符串进行hash算法算出分片。sharding-by-stringhash按天分片sharding-by-date按自然月分片sharding-by-month function namesharding-by-substring classio.mycat.route.function.PartitionDirectBySubStringproperty namestartIndex0/propertyproperty namesize2/propertyproperty namepartitionCount3/propertyproperty namedefaultPartition2/property /functionfunction namesharding-by-long-hash classio.mycat.route.function.PartitionByLongproperty namepartitionCount2,1/property!-- 约束分片长度默认 1024; count\length 数组长度必须一致 --property namepartitionLength256,512/property /functionfunction namesharding-by-stringhash classio.mycat.route.function.PartitionByStringproperty namepartitionLength512/propertyproperty namepartitionCount2/property!-- hash 运算位格式 start:end; 0 在end中出现代表 str.length(); -1 代表 str.length()-1大于0代表数字本身 --property namehashSlice0:2/property /function3.3.6 Mycat管理及监控 3.3.6.1 MyCat 原理 3.3.6.2 MyCat 管理 Mycat 默认开通2个端口可以在 server.xml 中进行修改。 8066 数据访问端口即进行 DML 和 DDL 操作。9066 数据库管理端口即 Mycat 服务管理控制功能用于管理 Mycat 的整个集群状态。 mysql -h 192.168.3.27 -P 9066 -u root -p123456Mycat-eye: Mycat-web(Mycat-eye) 是对 mycat-server 提供监控服务功能不局限于对 mycat-server 使用他通过 JDBC 连接对 Mycat、MySQL 监控监控远程服务器(目前仅限于Linux 系统)的cpu、内存、网络、磁盘。 Mycat-eye 运行过程中需要依赖 zookeeper。因此需要先安装 zookeeper。 # zookeeper 安装 wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.3/apache-zookeeper-3.8.3-bin.tar.gz tar -zxvf apache-zookeeper-3.8.3-bin.tar.gz -C /usr/local/ mkdir /usr/local/apache-zookeeper-3.8.3-bin/data bin/zkServer.sh start bin/zkServer.sh status # mycat-web 安装 需要先获取 MyCatWeb 压缩包 tar -zxvf Mycat-web-1.0-SNAPSHOT-20170102153329-linux.tar.gz -C /usr/local/ cd /usr/local/mycat-web/ sh start.sh # 访问 localhost:8082/mycat 访问3.4 读写分离 3.4.1 读写分离介绍 读写分离简单地说是把对数据库的读和写操作分开以对应不同的数据库服务器。主数据库提供写操作从数据库提供读操作这样能有效地减轻单台数据库的压力。 通过 MyCat 即可轻易实现上述功能不仅可以支持 MySQL也可以支持 Oracle 和 SQL Server。 3.4.2 一主一从读写分离 MyCat 控制后台数据库的读写分离和负载均衡由 schema.xml 文件 datahost 标签的 balance 属性控制。 !-- schema.xml -- schema nameDB_RW checkSQLschematrue sqlMaxLimit100 dataNodedn1 /schemadataNode namedn1 dataHostdhost1 databasetestdb/dataHost namedhost1 maxCon1000 minCon10 balance1 writeType0 dbTypemysql dbDriverjdbcheartbeatselect user()/heartbeatwriteHost hostmaster urljdbc:mysql://192.168.3.27:3306?useSSLfalse userroot password1234readHost hostslave urljdbc:mysql://192.168.3.28:3306?useSSLfalse userroot password1234//writeHost /dataHost!-- server.xml -- user nameroot defaultAccounttrueproperty namepassword123456/propertyproperty nameschemaDB_RW/property /user负载均衡 balance 取值的含义 0不开启读写分离机制所有读操作都发送到当前可用的 writeHost 上。1全部的 readHost 与备用的 writeHost 都参与 select 语句的负载均衡(主要针对于双主双从模式)2所有的读写操作都随机在 writeHost、readHost 上分发。3所有的读请求随机分发到 writeHost 对应的 readHost 上执行writeHost 不负担读压力。 问题 主节点 Master 宕机之后业务系统就只能够读而不能写入数据了。 3.4.3 双主双从读写分离 双主双从一个主机 Master1 用于处理所有写请求它的从机 slave1 和另一台主机 Master2 还有它的从机 slave2 负责所有读请求。当 Master1 主机宕机后Master2 主机负责写请求Master1 和 Master2 互为备机。 主库配置 master1 #修改 /etc/my.cnf # mysql 服务id,保证整个集群环境中唯一取值范围 1-2^32-1,默认为1. server-id1 #指定同步的数据库 binlog-do-dbdb01 binlog-do-dbdb02 binlog-do-dbdb03 # 在作为从数据库的时候有写入操作也要更新二进制日志文件 log-slave-updates主库配置 master2 #修改 /etc/my.cnf # mysql 服务id,保证整个集群环境中唯一取值范围 1-2^32-1,默认为1. server-id3 #指定同步的数据库 binlog-do-dbdb01 binlog-do-dbdb02 binlog-do-dbdb03 # 在作为从数据库的时候有写入操作也要更新二进制日志文件 log-slave-updates两台主库创建账户并授权 -- 创建 test 用户并设置密码该用户可在任意主机连接该 MySQL 服务 create user test% identified with mysql_native_password by 1123; -- 为 test 用户分配主从复制权限 grant replication slave on *.* to test%; -- 查看两台主库的二进制日志坐标 show master status;从库配置 slave1: #修改 /etc/my.cnf # mysql 服务id,保证整个集群环境中唯一取值范围 1-2^32-1,默认为1. server-id2从库配置 slave2: #修改 /etc/my.cnf # mysql 服务id,保证整个集群环境中唯一取值范围 1-2^32-1,默认为1. server-id4两台从库配置关联的主库 需要注意 slave1 对应的是 master1slave2 对应的是 master2 -- mysql 版本是 8.0.23 中语法如下 change replication source to source_hostxxx,source_userxxx,source_passwordxxx,source_log_filexxx,source_log_posxxx; -- mysql 版本是 8.0.23之前的版本语法如下 change master to master_hostxxx,master_userxxx,master_passwordxxx,master_log_filexxx,master_log_posxxx; -- 开启同步操作 -- 8.0.22 之后的语法 start replica; -- 8.0.22 之前的语法 start slave; -- 5. 查看主从同步状态 -- 8.0.22 之后的语法 show replica status\G; -- 8.0.22 之前的语法 show slave status\G;两台主库相互复制Master2 复制 Master1Master1 复制 Master2 -- mysql 版本是 8.0.23 中语法如下 change replication source to source_hostxxx,source_userxxx,source_passwordxxx,source_log_filexxx,source_log_posxxx; -- mysql 版本是 8.0.23之前的版本语法如下 change master to master_hostxxx,master_userxxx,master_passwordxxx,master_log_filexxx,master_log_posxxx; -- 开启同步操作 -- 8.0.22 之后的语法 start replica; -- 8.0.22 之前的语法 start slave; -- 5. 查看主从同步状态 -- 8.0.22 之后的语法 show replica status\G; -- 8.0.22 之前的语法 show slave status\G;双主双从的读写分离MyCat 控制后台数据库的读写分离和负载均衡由 schema 标签的 balance 属性控制通过 writeType 及 switchType 来完成失败自动切换。 !-- schema.xml -- schema nameDB_RW checkSQLschematrue sqlMaxLimit100 dataNodedn1 /schemadataNode namedn1 dataHostdhost1 databasetestdb/dataHost namedhost1 maxCon1000 minCon10 balance1 writeType0 switchType1 dbTypemysql dbDriverjdbc slaveThreahold100heartbeatselect user()/heartbeat!-- M1-S1 --writeHost hostmaster1 urljdbc:mysql://192.168.3.27:3306?useSSLfalse userroot password1234readHost hostslave1 urljdbc:mysql://192.168.3.28:3306?useSSLfalse userroot password1234//writeHost!-- M2-S2 --writeHost hostmaster2 urljdbc:mysql://192.168.3.27:3306?useSSLfalse userroot password1234readHost hostslave2 urljdbc:mysql://192.168.3.28:3306?useSSLfalse userroot password1234//writeHost /dataHost!-- server.xml -- user nameroot defaultAccounttrueproperty namepassword123456/propertyproperty nameschemaDB_RW/property /userbalance“1”: 代表全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡简单的说当双主双从模式(M1-S1,M2-S2),并且M1和M2互为主备。正常情况下M2、S1、S2都参与 select 语句的负载均衡。 writeType: 0: 写操作都转发到第一台 writeHost,writeHost 挂了会切换到writeHost2上。1: 所有的写操作都随机地发送到配置的 writeHost 上 switchType: -1: 不自动切换1: 自动切换 4. 面试题 为什么InnoDB存储引擎选择使用BTree索引结构 相对于二叉树层级更少搜索效率高 相对于 B-Tree, 无论叶子节点还是非叶子节点都会保存数据这样导致页中存储的键值减少指针跟着减少要同样保存大量数据只能增加树的高度导致性能降低。 相对于 Hash 索引 BTree 支持范围匹配和排序操作。 一张表有四个字段(id、username、password、status),由于数据量大需要对以下SQL语句进行优化该如何进行才是最优方案 -- username\password 建立联合索引 select id,username,password from user where username test;5.参考文献 黑马程序员 MySQl 官方网站 可视化数据结构演示 MySQL doc Mycat开源项目

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/912531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

建设网站公司怎么分工免费制作图片

大家好,我是晴天学长,搜索型的dfs,差点开二维矩阵了,仔细一想,没那么夸张啊,哈哈哈,需要的小伙伴可以关注支持一下哦!后续会继续更新的。💪💪💪 1…

OpenAI Codex 使用 智谱 API

安装 codex npm install -g @openai/codex --registry=https://registry.npmmirror.com/ 用户目录下的 .codex 目录( %userprofile%.codex )下创建 config.toml 文件 (需要替换 zhipu api key) model_provider = "…

嵌入式ARM架构学习9——IIC - 教程

嵌入式ARM架构学习9——IIC - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&…

山东青岛网站建设律师事务所免费咨询

正则表达式,又称正规表示法、常规表示法(Regular Expression,在代码中常简写为regex、regexp或RE),是计算机科学中的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器…

苏州市相城区住房和城乡建设局网站济南建设网站 概况

题意:给定n和m,求c(n,m)%(∏ p)的值,相当于lucas定理的一个推广,在p不是素数的情况下的一个解决方法。 思路: 首先对于c(n,m)%p[i]来讲,是一个lucas的裸题,那么对于c(n,m)%(∏ p)划分成lucas子…

网站推广赚钱吗做金融怎么进基金公司网站

在 MyBatis 中&#xff0c;< 符号在 XML 配置文件中是一个特殊字符&#xff0c;用于标记 XML 标签的开始。因此&#xff0c;如果你在 MyBatis 的 if 标签中直接使用 < 符号&#xff0c;它会被解析为 XML 标签的开始&#xff0c;从而导致解析错误。 为了避免这个问题&…

福建泉州做淘宝的拿货什么网站第一模板ppt网

一、故事引言 想象一下&#xff0c;你正在管理一座神奇的数据仓库&#xff0c;这个仓库没有沉重的门、旋转的磁盘和机械手臂&#xff0c;而是由一群训练有素的“数据小飞侠”组成。这些小飞侠们居住在一个叫做闪存芯片&#xff08;NAND Flash&#xff0c;本文主人公&#xff0…

营销型企业网站建设价格wordpress5.0.2版的新功能

aws sqsAmazon WEB服务为我们提供了SQS消息传递服务。 sqs的java sdk与JMS兼容。 因此&#xff0c;可以将SQS与spring提供的JMS集成框架集成在一起&#xff0c;而不是将SQS用作简单的spring bean。 我将使用spring-boot和gradle。 gradle文件&#xff1a; group com.gkatzi…

网站开发案例详解下载x浏览器

zencart 如何修改在线人数和订单编号 1 订单编号的修改办法 进入后台-工具(tool)-店铺管理器(store manager)&#xff0c;里面有个重置当前订单号&#xff08;Reset Current Order ID). 首先你得测试购买一次&#xff08;不要告诉我你不会&#xff09;&#xff0c;就会产生当前…

杭州市建设工程质量安全监督总站网站媒体广告投放平台

转载自 超详细的 Redis Cluster 官方集群搭建指南 今天从 0 开始搭建 Redis Cluster 官方集群&#xff0c;解决搭建过程中遇到的问题&#xff0c;超详细。 安装ruby环境 因为官方提供的创建集群的工具是用ruby写的&#xff0c;需要ruby2.2.2版本支持&#xff0c;ruby安装需…

网站设计任务怎么自己制作二维码内容

打家劫舍2 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址&#xff1a;点这里 2. 讲解算法原理 首先&#xff0c;给定一个非负整数数组 nums&#xff0c;其中 nums[i] 表示第 i 家的财物价值。 定义两个辅助数组 f 和 g&#xff0c;长度都为 n&#xff08;n 是…

长安镇网站建设东莞销售网站建设

## 资源简介 在STM32开发板,板载资源上有两个可自由控制的 LED。如下图原理 图其中我们以操作 LED1 为示例,LED1 为出厂系统的心跳指示灯。 ## 应用实例 想要控制这个 LED,首先出厂内核已经默认将这个 LED 注册成了 gpio-leds类型设备。所以我们可以直接在应用层接口直接…

微信小程序与网站连接互联网门户网站建设

Softing工业将ARM 32位兼容性集成到了edgeConnector产品中&#xff0c;以满足用户对ARM处理器的边缘设备日益增长的使用需求。 &#xff08;兼容ARM 32位架构的edgeConnector产品扩展了其应用部署范围&#xff09; 用户对采用ARM处理器的紧凑型边缘设备的需求正在大幅增长&…

就业专项资金网站建设北京外贸网站设计备案

C#上位机——根据命令发送 第一步&#xff1a;设置窗口的布局 第二步&#xff1a;设置各个属性 第三步&#xff1a;编写各个模块之间的关系

diango做的网站怎么用ppt在哪个软件制作

概述对于一些数据量较大的系统&#xff0c;数据库面临的问题除了查询效率低下&#xff0c;还有就是数据入库时间长。特别像报表系统&#xff0c;每天花费在数据导入上的时间可能会长达几个小时或十几个小时之久。因此&#xff0c;优化数据库插入性能是很有意义的。其实最有效的…

有几个网站如何做外贸海口网站公司

Python学习之路-Flask项目:博客前台 前言 前一篇完成了项目开发前的所有准备工作&#xff0c;本篇将完成整个博客的前台相关工作。 首页 前言 首页主要为我们提供各个分类入口已经按时间顺序的文章列表和列表排行等数据&#xff0c;是进入博客中第一眼看到的&#xff0c;接…

学院实验室建设网站的好处高州市网站建设

导语&#xff1a;之前介绍了如何打包一个安卓安装包文件&#xff0c;如果想要上架安卓应用商店&#xff0c;那么就来这里学习一下方法吧。 目录 准备材料应用商店注册账号上架步骤审核事项 准备材料 基本信息 安装包&#xff1a;需要 32 或 64 位&#xff1b;包名&#xff…

网站维护更新费用品牌建设的重要性与意义

一、JavaScript的面向对象 JavaScript其实支持多种编程范式的&#xff0c;包括函数式编程和面向对象编程&#xff1a; JavaScript中的对象被设计成一组属性的无序集合&#xff0c;像是一个哈希表&#xff0c;有key和value组成&#xff1b;key是一个标识符名称&#xff0c;val…

项目管理软件开发案例seo 资料包怎么获得

学习笔记-SQL语法系统性学习&#xff0c;关卡式进阶 笔记参考&#xff1a;作者鱼皮 关卡式Sql语句学习体验网站 &#xff0c;网站开源代码 如果想本地体验语法&#xff1a;1.下载大佬开源代码&#xff0c;运行前端项目&#xff08;推荐&#xff09;&#xff1b; 2.或是自己使…

饮食类网站绿盒子网站建设案例

iPhone 不能下载第三方软件的原因主要是因为苹果公司严格控制其应用生态系统&#xff0c;确保所有应用都通过其官方的 App Store 分发。这有几个主要原因&#xff1a; 安全性&#xff1a;苹果公司希望通过这种方式减少恶意软件的传播&#xff0c;保护用户的隐私和数据安全。所…