1、下载设置安装源
#下载安装源
wget http://repo.mysql.com/mysql57-community-release-el6-8.noarch.rpm
#安装rpm包
rpm -ivh mysql57-community-release-el6-8.noarch.rpm
#修改安装源
vim /etc/yum.repos.d/mysql-community.repo
将[mysql55-community]的enabled设置为1,[mysql57-community]的enabled设置为0
2、安装mysql
yum -y install mysql-server mysql
-----解决yum锁问题------
rm -f /var/run/yum.pid
3、设置
数据库字符集设置
mysql配置文件 /etc/my.cnf中加入
character-set-server=utf8
4、启动/停止 服务
启动mysql服务:
service mysqld start
或者
/etc/init.d/mysqld start
停止服务:
service mysqld stop
开机启动:
chkconfig mysqld on,查看开机启动设置是否成功chkconfig --list | grep mysql*
5、登录
查询mysql第一次安装时的随机密码:
grep 'password' /var/log/mysqld.log |head -n 1
创建root管理员:
mysqladmin -u root password 123456
登录:
mysql -u root -p输入密码即可
6、远程访问
开放防火墙的3306端口号
/etc/sysconfig/iptabls 添加端口记录:
重启防火墙
service iptables restart
创建远程访问用户:
create user 'root'@'%' identified by 'root';
7、授权
grant all privileges on *.* to 'root'@'%';
1、检查是否已经安装Mysql
#检查是否安装过mysql
rpm -qa | grep -i mysql
#卸载
rpm -e xxxxxx
2、下载Mysql相关RPM包
#下载相关rpm包
MySQL-client-5.6.40-1.el6.x86_64.rpm
MySQL-devel-5.6.40-1.el6.x86_64.rpm
MySQL-server-5.6.40-1.el6.x86_64.rpm
3、安装server->devel->client
#安装mysql服务
rpm -ivh MySQL-server-5.6.40-1.el6.x86_64.rpm
#安装mysql库信息
rpm -ivh MySQl-devel-5.6.40-1.el6.x86_64.rpm
#安装mysql客户端
rpm -ivh MySQl-client-5.6.40-1.el6.x86_64.rpm
4、将MySQL的配置文件拷贝到/etc目录下
#拷贝mysql配置文件
cp /usr/share/mysql/my-default.cnf /etc/my.cnf
#添加如下配置
port=3306
character-set-server=utf8
5、启动Mysql服务器
#启动服务器
service mysql start
6、查看root密码并且修改密码
#查看root账号随机密码
cat /root/.mysql_secret
#登录mysql服务器
mysql -uroot -p
#修改密码
7、配置远程访问
开放防火墙的3306端口号
/etc/sysconfig/iptabls 添加端口记录:
重启防火墙
service iptables restart
创建远程访问用户:
create user 'root'@'%' identified by 'root';
授权
grant all privileges on *.* to 'root'@'%';
主从复制
默认关闭,用于记录严重的警告和错误信息,每次启动和关闭的详细信息等
默认关闭,记录所执行的sql语句的执行信息
默认路径:/var/lib/mysql
/etc/my.cnf
1、最上层的服务并不是Mysql独有的,大多数基于网络的客户端/服务器的工具或者服务都有类似的架构;
2、第二层架构中,大多数的MYSQL的核心服务功能都在这一层,包括查询解析、分析、优化、缓存以及所有的内置函数(日期时间等),所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等;
3、第三层包含了存储引擎。存储引擎负责Mysql中的数据的存储和提取。Mysql支持各种不同的存储引擎,每个存储引擎都有它的优势和劣势。服务器通过API和存储引擎进行通信。这些API接口屏蔽了不同存储引擎之间的差异,使的这些差异对上层的查询过程透明。存储引擎不会解析SQL(InnoDB是个例外,它会解析外键定义),不同的存储引擎之间也不能互相通信,而只是简单的响应上层服务器的请求。
查询当前数据库所支持的存储引擎
show engines;
查询当前默认的存储引擎
show variables like '%storage_engine%'
查看表的相关信息
show table status like '表名'
字段含义
如果应用需要不同的存储引擎,请考虑一下几个因素:
Mysql支持的数据类型非常多,选择正确的数据类型对于获得高性能至关重要。
更小的通常更好:
通常情况下,应该选择可以正确存储数据的最小数据类型。更小的数据类型通常更快,因为它们占用更小的磁盘、内存和CPU缓存。但是要确保没有低估需要存储值得范围,在MYSQL中的多个地方增加数据类型范围是一个非常耗时和痛苦的操作。
简单就好:
简单数据类型的操作通常需要更少的CPU消耗。比如,整型比字符操作代价更低。举个例子:
①应该选择MySQL内建的类型(date、time等)存储时间,而不是字符串。
②应该用整型存储IP地址。
尽量避免NULL:
通常情况下最好执行列为NOT NULL,除非真的需要存储NULL值。如果查询总包含可能为NULL的列,对于MySQL来说更难优化,因为可为NULL的列使的索引、索引统计等都变的更加复杂。通常把字段设置为NOT NULL带来的性能提升比较小,但是如果计划在列上创建索引,就应该尽量避免设计成可为NULL的列。
实数是带小数部分的数字。
注意:varchar(5)和varchar(200)存储’hello’的空间开销是一样的。但是varchar(5)对性能提升有很大的优势。更长的列会消耗更多的内存,因为mysql通常会分配固定大小的内存块来保存内部值。尤其是使用内存临时表进行排序等操作时会特别糟糕。所以最好的策略是只分配真正需要的空间。
注意:除了特殊行为之外,通常应该尽量使用timestamp,因为它比datetime空间效率更高。
索引是存储引擎用于快速找到记录的一种数据结构。索引对于良好的数据库查询性能而言是非常关键的,尤其当表中的数据量越来越大时,索引对性能的影响越发重要。索引可以说是对查询性能优化最有效的手段了。因为索引能够轻易将查询性能提高几个数量级,将一个可能需要几百秒的查询语句提升到只需要几秒。但是索引经常被忽略,而不恰当的索引对性能可能还会带来负面效果,所以在使用索引的时候,需要考虑需求,不要一味的追求索引。
1、单值索引
一个索引只包含单个列,一个表可以有多个单列索引。
2、复合索引
一个索引包含多个列。
3、唯一索引
索引列的值必须唯一,但是允许有空值。
4、全文索引
全文索引,通过建立倒排索引,可以极大的提升检索效率,解决判断字段是否包含的问题.。例如: 有title字段,需要查询所有包含 "政府"的记录. 需要 like "%政府%“方式查询,查询速度慢,当查询包含"政府” OR "中国"的需要是,sql难以简单满足。全文索引就可以实现这个功能。
详细的自行百度。
5、索引的基本语法
create [unique|fulltext] index 索引名 on 表名 (属性名[长度][asc|desc]);
drop index 索引名 on 表名;
show index from 表名;
什么是B-tree索引?
通常我们所说的索引是指B-Tree索引,它是目前关系型数据库中查找数据最为常用和有效的索引,大多数存储引擎都支持这种索引。使用B-Tree这个术语,是因为MySQL在CREATE TABLE或其它语句中使用了这个关键字,但实际上不同的存储引擎可能使用不同的数据结构,比如InnoDB就是使用的B+Tree。
什么是哈希表?
自行百度
什么是二叉搜索树
自行百度
为什么采用B-tree设计索引而不用哈希表或者二叉搜索树?
随着数据库中数据的增加,索引本身大小随之增加,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级。可以想象一下一棵几百万节点的二叉树的深度是多少?如果将这么大深度的一颗二叉树放磁盘上,每读取一个节点,需要一次磁盘的I/O读取,整个查找的耗时显然是不能够接受的。那么如何减少查找过程中的I/O存取次数?
一种行之有效的解决方法是减少树的深度,将二叉树变为m叉树(多路搜索树),而B+Tree就是一种多路搜索树。理解B+Tree时,只需要理解其最重要的两个特征即可:第一,所有的关键字(可以理解为数据)都存储在叶子节点(Leaf Page),非叶子节点(Index Page)并不存储真正的数据,所有记录节点都是按键值大小顺序存放在同一层叶子节点上。其次,所有的叶子节点由指针连接。
注意:B-tree的非叶子节点也存放数据,B+树是B-tree的变种。
执行计划可以模拟Mysql优化器执行SQL查询语句,从而了解Mysql是如何处理被执行的SQL语句的。可以帮助程序员分析和了解这条SQL语句的性能瓶颈。
语法:
explain select语句
查询字段含义(这里只列举主要的字段):
作用:id主要是用来标识sql执行顺序。
id相同:如果没有子查询时会出现,执行顺序也是从上到下。
#查询所有学生
explain select * from student;
#关联查询所有学生和班级信息
explain select * from student s inner join class c on s.cid = c.id;
id不同:如果是子查询,则每个查询会有不同的id,并且依次递增。id值越大,表示优先级越高,越先被执行
#查询id为1的班级中的所有学生信息
explain select * from student where cid = (select id from class where id = 1)
id相同不同,同时存在:先查询id值大的,id相同,从上到下顺序执行
#
explain select * from (select * from student) s inner join class c on c.id = s.id
id为null的情况,如果id为null表示该部分最后执行
作用:每个select子句的类型。
mysql对查询的分类:
explain select * from student;
PRIMARY:查询中包含了任何复杂的子部分,最外层的就会变成PRIMARY (最后被执行的查询)
#
explain select * from student where cid = (select id from class where id = 1);
#
explain select * from (select * from student) s inner join class c on c.id = s.id
SUBQUERY:在SELECT或者WHERE列表中的子查询标记为 SUBQUERY
explain select * from student where cid = (select id from class where id = 1);
DERIVED:在FROM中包含的子查询被标记为 DERIVED(衍生表)
explain select * from (select * from student) s
UNION:如果第二个SELECT出现在UNION之后,则被标记为UNION,如果UNION包含在FROM子句的子查询中,第一个SELECT会被标记为:DERIVED
#
explain
select * from student where score <= 1
union
select * from student where score >= 1.5
#
explain
select * from
(select * from student where score <= 1
union
select * from student where score >= 1.5) s
UNION RESULT:从UNION表获取结果的select
explain
select * from student where score <= 1
union
select * from student where score >= 1.5
作用:表示访问类型,换而言之就是Mysql查找表中行的方式,下面的访问方式,从最差到最优。
null > system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
all:表示全表扫描,效率最低
#
explain select * from student where name = '小明';
#
explain select * from student where age > 5;
index:这个跟全表扫描一样,只是MySQL扫描表时,按索引次序进行而不是行。它的主要作用是避免了排序;缺点是要承担按索引次序读取整个表的开销;如果在extra中看到’Using index’,说明MySQL正在使用覆盖索引,它只扫描索引的数据,而不是按索引次序的每一行,这样效率就会高效很多。
#
explain select id from student
#
explain select * from student order by id
range:范围扫描就是一个有限制的索引扫描,它开始于索引里的某一点,返回匹配这个值域的行
#
explain select * from student where id > 2
ref:这是一种索引访问,它返回所有匹配某个值得行。然后它可能会找到多个符合条件的行,因此它是查找和扫描的混合体。此类访问只有使用非唯一索引或者唯一索引的非唯一性前缀时才会发生。
#创建索引
create index index_age on student(age);
#
explain select * from student where age = 5
eq_ref:使用这种搜索查找,Mysql知道最多只返回一条符合条件的记录。这种访问方法可以在Mysql使用主键或者唯一性索引联合查询时看到
explain select * from student s inner join class c on s.cid = c.id
const:当Mysql能对查询的某部分进行优化并将其转换成一个常量时,它就会使用这些访问类型。举例来说,当你通过某一行的主键放入where字句里的方式来查询时,MySQL会把这部分操作转换为一个常量。就是直接取数据。
explain select * from student where id = 1
system:表只有一行记录,这是const类型的特例,通常不会出现。
explain select * from (select * from student where id = 1) s
NULL:这种方式意味着MySQL能在优化阶段分解查询语句,在执行阶段甚至用不着再访问表或索引。这是最优的效果。
#
explain select 1+2;
#
explain select * from student where id = 1 and id = 2
**注意:**通常在生产环境中,得保证查询至少达到range级别,最好能达到ref级别以上。
可能应用到这个查询上的索引。
实际使用的索引,如果为NULL,则没有使用任何索引。如果该索引没有出现在possible_keys列中,那么Mysql选用它就是出于另外的原因。换句话说,possible_keys表示哪个索引能有助于高效的行查找,而key显示的是优化采用哪个索引可以最小化查询成本。
使用索引的长度,在不损失精准性的情况下,长度越短越好。
表示查询记录时,所用到列或常量。
这一列是MySQL估计为了查找所需的记录而需要读取的行数,他不一定等于最终从表里读取出来的行数。
关于MYSQL如何解析查询的额外信息。
正确的创建和使用索引是实现高性能查询的基础。
为什么选择多列索引,而不是每个列单独创建索引?
在多数情况下,在多个列上建立独立的索引并不能提高查询性能。理由非常简单,MySQL不知道选择哪个索引的查询效率更好,所以在老版本,比如MySQL5.0之前就会随便选择一个列的索引,而新的版本会采用合并索引的策略。
** 选择合适的索引顺序:** 应该将选择性更高的列放在前面。
** 注意:** 当出现多个索引做相交操作时(多个AND条件),通常来说一个包含所有相关列的索引要优于多个独立索引。当出现多个索引做联合操作时(多个OR条件),对结果集的合并、排序等操作需要耗费大量的CPU和内存资源,特别是当其中的某些索引的选择性不高,需要返回合并大量数据时,查询成本更高。所以这种情况下还不如走全表扫描。
索引列不能是表达式的一部分,也不能是函数的参数。应该养成简化where条件的习惯,始终将索引列单独放在运算符的一侧。
select * from ... where id + 1 = 5;
这是一个错误的用法,mysql无法解析id + 1 = 5 这个方程式,故不会使用到id列上的索引。
什么是前缀索引?
有时候需要索引很长的字符列,这会让索引变得很大且慢。通常可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。但是这样也会降低索引的选择性。
创建前缀索引语法
CREATE INDEX 索引名 ON 表名 (字段名(前缀长度))
索引选择性
什么是索引选择性?
索引的选择性是指,不重复的索引值和数据表的总记录的比值。索引选择性越高则查询效率越高,索引选择性可以让mysql在查询时过滤掉更多的行。
计算完整列的选择性:
select count(distinct 列名)/count(*) from 表名
选择合适的前缀索引长度
前缀索引的长度选择应该在一个合适的范围,不能太长同时要保证较高的选择性。前缀索引的选择性应该接近于完整列的选择性。
计算前缀索引的选择性
select count(distinct left(列名, 长度))/count(1) from 表名
注意:前缀索引也有缺点,mysql无法使用前缀索引做order by和group by
和索引中的所有列进行匹配。
和索引中的第一列进行匹配。
和索引中的第一列的开头部分进行匹配。比如:like ‘a%’
和索引中的第一列的范围匹配。
第一列全值匹配,第二列范围匹配。
什么是聚簇索引?
聚簇索引实际上就是在同一个结构中保存了B-tree索引和数据行。
创建聚簇索引
MySQL无法主动创建聚簇索引,InnoDB是将我们的主键作为聚簇索引。如果没有定义主键,则InnoDB会选择一个唯一的非空索引代替。如果没有这样的索引,则InnoDB会隐式的定义一个主键来作为聚簇索引。
二级索引
二级索引即普通索引,和聚簇索引不同。二级索引的叶子节点中存储的不是行指针,而是主键值。即二级索引的叶节点都指向聚簇索引对应的主键。
**注意:**在使用InnoDB表时,应该提供一个自动增长的列作为主键,这种主键和业务应该无关,这样可以保证数据行是按顺序写入,对于根据主键做关联操作的性能也会更好。
如果一个索引包含或者说覆盖所有需要查询的字段的值,那么就没有必要再回表查询,这就称为覆盖索引。
**优势:**索引条目远小于数据行大小,如果只读取索引,极大减少数据访问量;索引是有按照列值顺序存储的,对于I/O密集型的范围查询要比随机从磁盘读取每一行数据的IO要少的多。
后续补充。。。。。
当前有索引index(a,b,c),问以下的查询是否能用到索引,如果用上了,则哪几个字段会用上索引?
sql语句的编写顺序:
select 列名1,列名2...
from 表名1
[inner join 表名2 on 表名1.公共列=表名2.公共列]
[left join 表名2 on 表名1.公共列=表名2.公共列]
[right join 表名2 on 表名1.公共列=表名2.公共列]
[where 条件//边查询边筛选]
[group by 列名 //查询完后再将结果进行分组]
[having 条件 //查询完分完组后再筛选 ]
[order by 列名[asc/desc] //对结果排序]
[limit start [,count]]//只有mysql可用;
分析
从这个顺序中我们不难发现,所有的 查询语句都是从from开始执行的,在执行过程中,每个步骤都会为下一个步骤生成一个虚拟表,这个虚拟表将作为下一个执行步骤的输入。
什么是慢查询日志?
MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阈值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为10,意思是运行10S以上的语句。默认情况下,Mysql数据库并不启动慢查询日志,需要我们手动来设置这个参数,当然,如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志记录写入文件,也支持将日志记录写入数据库表。
开启慢查询日志
查看慢查询日志:
select @@slow_query_log;
开启:
SET GLOBAL slow_query_log=1;
查询慢查询次数
show status like 'slow_queries';
设置慢查询的阈值
查看阈值:
show variables like 'long%'
设置阈值:
set long_query_time=0.001;
查看慢查询日志的位置
select @@slow_query_log_file;
注意:每次删除慢查询日志,需要重新开启慢查询,日志才会自动生成
什么是Show Profile?
mysql提供的,可以用来分析当前会话中语句执行的资源消耗情况。
查询当前Mysql版本是否支持Show Profile
show variables like 'profiling';
开启Show Profiling
set profiling = on;
查看Show Profiling记录
show profiles;
诊断SQL
show profile cpu,block io for query 'N'
其中N是记录下来的sql语句id
需要优化的步骤
表结构
#学生表
create table student(
id int primary key auto_increment,
name varchar(20) not null,
age int,
score float,
birthday timestamp,
cid int
);
#课程表
create table course(
id int primary key auto_increment,
cname varchar(10)
);
#成绩表
create table score(
sid int,
cid int,
score int default 0
);
insert into course
values
(null, "高等数学"),
(null, "线性代数"),
(null, "毛泽东思想"),
(null, "邓小平理论"),
(null, "马克思主义"),
(null, "计算机电路基础"),
(null, "操作系统"),
(null, "Mysql数据库"),
(null, "Oracle数据库"),
(null, "Java编程"),
(null, "C语言基础"),
(null, "二进制"),
(null, "概率学"),
(null, "大学英语"),
(null, "专业英语"),
(null, "PHP编程"),
(null, "C++"),
(null, "Pythod编程"),
(null, "云计算"),
(null, "大数据");
#批量插入学生记录
drop procedure if exists insert_stu;
delimiter &&
create procedure insert_stu()
begin
declare i int default 0;
A:loop
insert into student value(null, concat("小明",i), i, rand(), now(), rand()*20);
set i = i + 1;
if i >= 200000 then
leave A;
end if;
end loop;
end &&
delimiter ;
call insert_stu();
#批量插入学生成绩
drop procedure if exists insert_score;
delimiter &&
create procedure insert_score()
begin
declare i int default 1;
declare j int default 1;
A:loop
set j = rand() * 20 + 1;
B:loop
insert into score value(i, j, rand() * 100);
set j = j + rand() * 5 + 1;
if j > 20 then
leave B;
end if;
end loop B;
set i = i + 1;
if i > 200000 then
leave A;
end if;
end loop A;
end &&
delimiter ;
call insert_score();
#课程表20条
select count(*) from course;
#成绩表 70W+条
select count(*) from score;
#学生表 20W条
select count(*) from student;
优化前
select count(1) from score
优化后
select count(*) from score
注意: COUNT()可能是被大家误解最多的函数了,它有两种不同的作用,其一是统计某个列值的数量,其二是统计行数。统计列值时,要求列值是非空的,它不会统计NULL。如果确认括号中的表达式不可能为空时,实际上就是在统计行数。最简单的就是当使用COUNT(* ) 时,并不是我们所想象的那样扩展成所有的列,实际上,它会忽略所有的列而直接统计所有的行数。
我们最常见的误解也就在这儿,在括号内指定了一列却希望统计结果是行数,而且还常常误以为前者的性能会更好。但实际并非这样,如果要统计行数, 直接使用COUNT(*),意义清晰,且性能更好。
优化前
#创建索引
create index idx_name on student(name)
#
select * from student where student.name like '%生%'
#根据执行计划可知是全表扫描
优化后
#通过覆盖索引提高效率
select name from student where student.name like '%生%'
优化前
select * from student order by age
优化后
#创建索引
create index idx_age on student(age, name);
#
select name,age from student order by age
优化前
#未优化 - 子查询
select * from student where id in (select sid from score where cid = (select id from course where cname = '课程1') and score = 100);
#耗时 628.787771秒左右
优化后
#未添加索引 - 改成关联查询
select * from student st inner join score sc on st.id = sc.sid inner join course c on sc.cid = c.id where c.cname = '课程1' and sc.score = 100;
#耗时 0.167155秒左右
#添加索引
create index idx_cname on course(cname);
create index idx_cid_sco on score(cid, sid, score);
#添加索引后 - 子查询
select * from student where id in (select sid from score where cid = (select id from course where cname = '课程1') and score = 100);
#耗时 0.500977秒左右
#添加索引后 - 关联查询
select * from student st inner join score sc on st.id = sc.sid inner join course c on sc.cid = c.id where c.cname = '课程1' and sc.score = 100;
#耗时 0.042039秒左右
分页查询时可能存在的问题
分页的问题在于,当偏移量很大时,例如limit 100000,10 ;mysql需要查询100010条记录,但是只返回最后10条,前面的100000条记录都将被抛弃,代价很高。
解决方案
对于偏移量很大的时候,我们可以采用覆盖索引+延迟关联来解决这个问题。
延迟关联:通过使用覆盖索引查询返回需要的主键,再根据主键关联原表获得需要的数据。
例如:
优化前:
select film_id,description from film order by title LIMIT 100,10;
优化后:
select f.film_id,f.description
from film f
INNER JOIN
(select film_id from film order by title limit 100,10) b
on f.film_id=b.film_id;
什么是分区表?
表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分。从逻辑上看,只有一张表,但是底层却是由多个物理分区组成。
分区表适用的场景
查询Mysql是否支持分区
show variables like '%partition%';
分区表的类型
partition by range(exp)( //exp可以为列名或者表达式,比如to_date(created_date)
partition p0 values less than(num)
)
案例
create table emp(
id INT NOT null,
store_id int not null
)
partition by range(store_id)(
partition p0 values less than(10),
partition p1 values less than(20)
);
上面的语句创建了emp表,并根据store_id字段进行分区,小于10的值存在分区p0中,大于等于10,小于20的值存在分区p1中。 注意每个分区都是按顺序定义的,从最低到最高。
范围分区的问题
range范围覆盖问题:当插入的记录中对应的分区键的值不在分区定义的范围中的时候,插入语句会失败。
解决方案
设置分区的时候,使用values less than maxvalue 子句,MAXVALUE表示最大的可能的整数值。
partition by list(exp)( //exp为列名或者表达式
partition p0 values in (3,5) //值为3和5的在p0分区
)
注意:如果插入的记录对应的分区键的值不在list分区指定的值中,将会插入失败。并且,list不能像range分区那样提供maxvalue。
partition by hash(store_id) partitions 4;
#根据store_id对4取模,决定记录存储位置。 比如store_id = 234的记录,MOD(234,4)=2,所以会被存储在第二个分区
注意:常规Hash分区的优点和不足 。
优点:能够使数据尽可能的均匀分布。
缺点:不适合分区经常变动的需求。
partition by key(exp) partitions 4;//exp是零个或多个字段名的列表
查询优化
在where条件中带入分区列,有时候即时看上去多余也要带上。
执行计划查看分区
EXPLAIN PARTITIONS
MyCat介绍
一个彻底开源的,面向企业应用开发的大数据库集群;它支持事务、ACID、可以替代MySQL的加强版数据库;是一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群;是一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server;结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品;一个新颖的数据库中间件产品。
MyCat的运用场景
1、读写分离
2、分库分表
3、多数据源处理
…
MyCat安装(centos)
tar -zxf Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
#配置环境变量
vim /etc/profile
#添加内容
MYCAT_HOME=/usr/local/mysql/mycat
PATH=$PATH:$MYCAT_HOME/bin
export MYCAT_HOME PATH
#生效环境变量
source /etc/profile
开放端口8066和9066
MyCat的默认数据端口为8066,mycat通过这个端口接收数据库客户端的访问请求。管理端口为9066,用来接收mycat监控命令、查询mycat运行状况、重新加载配置文件等。
Mycat启动命令
#启动mycat
mycat start
#按控制台的方式启动mycat
mycat console
#停止mycat
mycat stop
MyCat核心配置文件
server.xml:用户管理及相关系统配置。
schema.xml:逻辑库、表等相关配置。
rule.xml:分片规则相关配置。
MyCat处理读写分离
MySQL主从复制
主从复制的过程
1)在主库上把数据更改记录到二进制日志(Binary Log)中(这些记录被称为二进制日志事件)。在每次准备提交事务完成数据更新前会进行这一步的操作。
2)从库将主库的日志复制到自己的中继日志中(Relay Log)。首先从库会启动一个工作线程(I/O线程),跟主库建立一个连接,然后在主库上启动一个特殊的二进制转储线程,这个二进制转储线程会读取主库上二进制日志中的事件。从库的I/O线程会将接收到的事件记录到中继日志中。
3)从库的SQL线程会读取中继日志中的事件,并在从库上执行,从而实现从库的数据同步。
配置主从复制
步骤
1)、在每台服务器上创建复制账号;
2)、配置主库和从库;
3)、通知从库连接到主库并从主库复制数据;
创建复制账号
GRANT REPLICATION SLAVE, REPLICATION CLIENT
ON *.*
TO 'repl'@'%'
IDENTIFIED BY 'repl'
配置主库
my.cnf文件中:
[mysqld]
server_id=1
log_bin=mysql-binlog
binlog_do_db=mydb
log_bin表示二进制文件的名称;server_id表示服务器的标识,唯一就行了;binlog_do_db表示需要复制的主数据库名字。
查看主库的二进制文件状态
show master status;
配置从库
log_bin = mysql-bin
server_id = 2
relay_log = /var/lib/mysql/mysql-relay-bin
log_slave_updates = 1
relay_log表示配置中继日志的位置与文件名;log_slave_updates表示允许从库将重放的事件也记录到自身的二进制日志中。
配置从库连接主库
CHANGE MASTER TO MASTER_HOST='192.168.101.148',
MASTER_USER='repl',
MASTER_PASSWORD='repl',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=0;
查看slave状态
show slave status;
开启复制
start slave
MyCat搭建读写分离服务
MyCat配置
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="rc_schema2" checkSQLschema="false" sqlMaxLimit="100" dataNode="rc_dn2">schema>
<dataNode name="rc_dn2" dataHost="dtHost2" database="mydb" />
<dataHost name="dtHost1" maxCon="500" minCon="20" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
<heartbeat>show slave statusheartbeat>
<writeHost host="master" url="192.168.101.130:3306" user="root" password="root" >
<readHost host="slave" url="192.168.101.131:3306" user="root" password="root" />
writeHost>
dataHost>
mycat:schema>
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<property name="useSqlStat">0property>
<property name="useGlobleTableCheck">0property>
<property name="sequnceHandlerType">2property>
<property name="processorBufferPoolType">0property>
<property name="handleDistributedTransactions">0property>
<property name="useOffHeapForMerge">1property>
<property name="memoryPageSize">1mproperty>
<property name="spillsFileBufferSize">1kproperty>
<property name="useStreamOutput">0property>
<property name="systemReserveMemorySize">384mproperty>
<property name="useZKSwitch">trueproperty>
system>
<user name="root">
<property name="password">rootproperty>
<property name="schemas">rc_schema2property>
user>
mycat:server>
MyCat处理分库分表
什么是分表?
水平拆分
水平分表就是根据一列或多列数据的值把数据行放到多个独立的表里,这里不具备业务意义。用于解决解决表行数过大问题。
垂直拆分
垂直分表就是把一个数据量很大的表,可以按某个字段的属性或使用频繁程度分类,拆分为多个表。解决列过长问题。
什么是分库?