庞丽静
笔记 https://gitee.com/panglijing/dba
准备软件是
[root@ip176-121-205-88 ftp]# cd /linux-soft/4/mysql/
[root@ip176-121-205-88 mysql]# ls
libev-4.15-1.el6.rf.x86_64.rpm
maxscale-2.1.2-1.rhel.7.x86_64.rpm
mha-soft-student
Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
my.cnf
mysql-5.7.17.tar
mysql-5.7.20-linux-glibc2.12-x86_64.tar.gz
percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm
phpMyAdmin-2.11.11-all-languages.tar.gz
pxc
schema.xml
[root@ip176-121-205-88 mysql]# scp mysql-5.7.17.tar 192.168.4.50:/root/
mysql-5.7.17.tar 100% 543MB 115.1MB/s 00:04
数据库介绍
存储数据的仓库
生活中的数据
常见的软件
开源软件不等于免费
专业术语(行业黑话)
[root@localhost ~]# tar xf mysql-5.7.17.tar
[root@localhost ~]# ls
mysql-5.7.17.tar
mysql-community-client-5.7.17-1.el7.x86_64.rpm
mysql-community-common-5.7.17-1.el7.x86_64.rpm
mysql-community-devel-5.7.17-1.el7.x86_64.rpm
mysql-community-embedded-5.7.17-1.el7.x86_64.rpm
mysql-community-embedded-compat-5.7.17-1.el7.x86_64.rpm
mysql-community-embedded-devel-5.7.17-1.el7.x86_64.rpm
mysql-community-libs-5.7.17-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.17-1.el7.x86_64.rpm
mysql-community-minimal-debuginfo-5.7.17-1.el7.x86_64.rpm
mysql-community-server-5.7.17-1.el7.x86_64.rpm
mysql-community-test-5.7.17-1.el7.x86_64.rpm
[root@localhost ~]# rpm -q mariadb-server
未安装软件包 mariadb-server
[root@localhost ~]# rpm -q mariadb
未安装软件包 mariadb
# 这两个软件都需要不存在,如果有的话,就需要先停止服务,删除软件,删除配置文件
systemctl stop mariadb
rpm -e --nodeps mariadb mariadb-server
rm -rf /etc/my.cnf
rm -rf /var/lib/mysql/*
[root@localhost ~]# yum -y install mysql-community-*.rpm
[root@localhost ~]# systemctl start mysqld # 只有第一次启动的时候才会初始化数据
[root@localhost ~]# ls /var/lib/mysql # 存储数据的文件夹
auto.cnf ib_buffer_pool mysql public_key.pem
ca-key.pem ibdata1 mysql.sock server-cert.pem
ca.pem ib_logfile0 mysql.sock.lock server-key.pem
client-cert.pem ib_logfile1 performance_schema sys
client-key.pem ibtmp1 private_key.pem
[root@localhost ~]# systemctl enable mysqld # 设置开机自启
[root@localhost ~]# ss -tunlp | grep 3306 # 端口是3306
tcp LISTEN 0 80 :::3306 :::* users:(("mysqld",pid=1049,fd=22))
[root@localhost ~]# ps -C mysqld
PID TTY TIME CMD
1049 ? 00:00:00 mysqld
查看初始密码
[root@localhost ~]# ls /var/log/mysqld.log
/var/log/mysqld.log
[root@localhost ~]# grep -i "password" /var/log/mysqld.log # -i 是忽略字母大小写
2022-02-07T02:15:34.952961Z 1 [Note] A temporary password is generated for root@localhost: z%s=b1Dg*8Wm # 冒号空格后面的才是密码
[root@localhost ~]# mysql -hlocalhost -uroot -p'z%s=b1Dg*8Wm'
-h 指定登录的服务器
-u 指定用户
-p 后面需要加‘’避免出现特殊字符而报错:指定密码
ctrl +l 清屏
初次登录必须修改密码
mysql> alter user root@"localhost" identified by "123qqq...A";
# identified 是指定密码的
mysql> show databases;
退出
mysql> exit ;
Bye
再次登录
[root@localhost ~]# mysql -uroot -p'123qqq...A'
自己访问自己,-hlocalhost 可以省略
多准备一台192.168.4.51的机器,一样的操作。密码设置为”NSD2110…a"
mysql> select version(); #查看服务器软件版本
mysql> select user(); #查看登录用户
mysql> show databases; #查看当前所在的库
mysql> select database(); #查看已有的库
mysql> use mysql; #切换库
Database changed
mysql> show tables ; #查看已有的表
相关参数
[root@mysql1 ~]# ls /etc/my.cnf # 主配置文件
/etc/my.cnf
[root@mysql1 ~]# ls /var/lib/mysql # 数据库的文件
auto.cnf ib_buffer_pool mysql public_key.pem
ca-key.pem ibdata1 mysql.sock server-cert.pem
ca.pem ib_logfile0 mysql.sock.lock server-key.pem
client-cert.pem ib_logfile1 performance_schema sys
client-key.pem ibtmp1 private_key.pem
# 端口号 3306
# 进程名 mysqld
# 传输协议 TCP
# 进程所有者 mysql
# 进程所属组 mysql
# 错误日志文件 服务日志 /var/log/mysqld.log
密码策略
mysql> show variables like "%password%"; %是模糊搜索
+---------------------------------------+--------+
| Variable_name | Value |
+---------------------------------------+--------+
| default_password_lifetime | 0 |
| disconnect_on_expired_password | ON |
| log_builtin_as_identified_by_password | OFF |
| mysql_native_password_proxy_users | OFF |
| old_passwords | 0 |
| report_password | |
| sha256_password_proxy_users | OFF |
| validate_password_check_user_name | OFF |
| validate_password_dictionary_file | |
| validate_password_length | 8 | # 这个是密码的长度
| validate_password_mixed_case_count | 1 |
| validate_password_number_count | 1 |
| validate_password_policy | MEDIUM | # 这个是密码策略
| validate_password_special_char_count | 1 |
+---------------------------------------+--------+
14 rows in set (0.03 sec)
mysql> set global validate_password_policy = 0 ; 0 就是最低级别
mysql> show variables like "%password%";
+---------------------------------------+-------+
| Variable_name | Value |
+---------------------------------------+-------+
| default_password_lifetime | 0 |
| disconnect_on_expired_password | ON |
| log_builtin_as_identified_by_password | OFF |
| mysql_native_password_proxy_users | OFF |
| old_passwords | 0 |
| report_password | |
| sha256_password_proxy_users | OFF |
| validate_password_check_user_name | OFF |
| validate_password_dictionary_file | |
| validate_password_length | 8 | # 这个是密码的长度
| validate_password_mixed_case_count | 1 |
| validate_password_number_count | 1 |
| validate_password_policy | LOW | # 显示当前的密码等级
| validate_password_special_char_count | 1 |
+---------------------------------------+-------+
14 rows in set (0.00 sec)
mysql> set global validate_password_length = 6 ;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like "%password%";
+---------------------------------------+-------+
| Variable_name | Value |
+---------------------------------------+-------+
| default_password_lifetime | 0 |
| disconnect_on_expired_password | ON |
| log_builtin_as_identified_by_password | OFF |
| mysql_native_password_proxy_users | OFF |
| old_passwords | 0 |
| report_password | |
| sha256_password_proxy_users | OFF |
| validate_password_check_user_name | OFF |
| validate_password_dictionary_file | |
| validate_password_length | 6 | # 这个是密码的长度
| validate_password_mixed_case_count | 1 |
| validate_password_number_count | 1 |
| validate_password_policy | LOW | # 显示当前的密码等级
| validate_password_special_char_count | 1 |
+---------------------------------------+-------+
14 rows in set (0.00 sec)
mysql> alter user root@"localhost" identified by "123456";
Query OK, 0 rows affected (0.00 sec)
。。。
[mysqld]
validate_password_policy=0
validate_password_length=6
。。。
[root@mysql1 ~]# systemctl restart mysqld # 重启不报错就可以了
[mysqld]
skip-grant-tables # 跳过授权表
#validate_password_policy=0
#validate_password_length=6
# 再次登录的时候就可以直接输入mysql
systemctl restart mysqld # 重启服务
mysql # 无密码登录
mysql> update mysql.user set authentication_string=password("654321")
-> where user="root" and host="localhost"; # 修改密码
mysql> flush privileges; # 刷新权限
mysql> exit # 退出连接
Bye
[root@mysql1 ~]# vim /etc/my.cnf
[mysqld]
#skip-grant-tables # 注释
validate_password_policy=0
validate_password_length=6
[root@mysql1 ~]# systemctl restart mysqld # 重启服务
[root@mysql1 ~]# mysql -uroot -p654321 # 新密码登录
具体操作如下:(必须要重启数据库的服务:不适合线上服务器)
不停止数据库的情况下破解数据库管理员的密码
必须借助其他的服务器的
用其他的服务器密码去覆盖不知道的服务器密码
[root@mysql2 ~]# ls /var/lib/mysql
auto.cnf ib_buffer_pool mysql public_key.pem
ca-key.pem ibdata1 mysql.sock server-cert.pem
ca.pem ib_logfile0 mysql.sock.lock server-key.pem
client-cert.pem ib_logfile1 performance_schema sys
client-key.pem ibtmp1 private_key.pem
都是存储到mysql这个文件夹中
[root@mysql1 ~]# scp -r 192.168.4.51:/var/lib/mysql/mysql /var/lib/mysql
[root@mysql1 ~]# kill -l # 查看所有的信号
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
[root@mysql1 ~]# which pstree
/usr/bin/pstree
如果没有的话,yum -y install psmisc 这个是pstree 命令的软件包
[root@mysql1 ~]# pstree -p | grep mysql | head -1
|-mysqld(2301)-+-{mysqld}(2302)
[root@mysql1 ~]# kill -SIGHUP 2301 # 发送-SIGHUP信号给父进程
[root@mysql1 ~]# ss -tunlp | grep 3306
tcp LISTEN 0 80 :::3306 :::* users:(("mysqld",pid=2301,fd=32))
[root@mysql1 ~]# mysql -uroot -p'NSD2110...a'
破解线上数据库服务器的管理员root密码
具体操作步骤如下
登录前修改:mysqladmin
等效于alter user 命令(登录后修改)
[root@mysql1 ~]# mysqladmin -uroot -p"NSD2110...a" password "123456"
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 5.7.17 MySQL Community Server (GPL)
[root@mysql1 ~]# mysqladmin -uroot -p password
回车,不明文输入密码
连接方式
常用如性软件 | 操作系统 | 说明 |
---|---|---|
Mysql-workbench | 跨平台 | Mysql官方提供 |
Mysql-Fromt | windows | 开源,轻量级客户端软件 |
Navicat | Windows | 专业,功能强大,商业版 |
phpMyAdmin | 跨平台 | 开源,需LAMP平台 |
yum -y install httpd php php-mysql
systemctl restart httpd
systemctl enable httpd.service
tar xf phpMyAdmin-2.11.11-all-languages.tar.gz
mv phpMyAdmin-2.11.11-all-languages /var/www/html/phpMyAdmin
cd /var/www/html/phpMyAdmin/
cp config.sample.inc.php config.inc.php # 创建主配置文件
vim +17 config.inc.php # 在‘’号里添加plj123 这个类似与验证码,可以随便写,但不可以没有
接下来直接在真机的浏览器中访问http://192.168.4.50/phpMyAdmin
用户名和密码都是数据库的用户名和密码
就是命令行登入界面的环境
安装sqljoy这个软件可以直接tab
根据命令功能分类如下:
查询使用的命令是select:对数据做查询的命令
语法格式:
命令格式
命令 | 说明 | 例子 |
---|---|---|
as 或空格 | 别名 | select name 用户名,homedir as 家目录 from tarena.user |
concat() | 拼接 | select concat(name,‘-’,uid) from user ; 任意字段为NULL返回值为null |
distinct | 去重 | select distinct gid from user ; |
数值比较
符号两边必须是数据类型
select * from user where uid =3 ;
比较符号 | 说明 |
---|---|
= | 等于 |
> | 大于 |
>= | 大于或等于 |
< | 小于 |
<= | 小于或等于 |
!= | 不等于 |
字符比较/匹配空/非空
比较符号 | 说明 | 例子 |
---|---|---|
= | 等于 | name =“root” |
!= | 不等于 | name != “root” |
is null | 空 | shell is null |
is not null | 非空 | shell is not null |
范围匹配
比较符号 | 说明 |
---|---|
in(值列表) | 在…里… |
not in (值列表) | 不在…里… |
between 数字 and 数字 | 在…之间 |
模糊匹配
where 字段名 like '通配符'
_表示1个字符
%表示0到多个字符
正则匹配
where 字段名 regexp '正则表达式'
元字符:
^ 行首
$ 行尾
. 1个字符
[] 范围内
* 前面表达式出现0或多次
| 或
准备环境
[root@mysql1 ~]# mysql -uroot -p123456 < tarena.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql> show databases;
mysql> select * from tarena.user; # 所有表头
mysql> select id,name,uid from user ; # 多个表头
mysql> select id,name,uid from user where uid<10; # 后面的就是筛选条件
mysql> select name as 姓名 from user ; #as 或 空格都是可以的
mysql> select concat(name,'-',uid) as 姓名 from user where uid < 5 ; # 拼接 任意字段为 NULL返回值null
mysql> select distinct shell from tarena.user; # 去重
mysql> select * from user where id <=3 ;
mysql> select * from user where id = 1;
mysql> select * from user where id != 1 ;
显示的内容太多了
mysql> select id,name,uid,gid from user where uid = gid ;
mysql> select name,shell from user where shell != "/bin/bash";
mysql> select name,shell from user where shell ="/bin/bash";
mysql> select name from user where id = 1 ;
mysql> select name from user where id = 1 and name is not null; # 这个是两个条件都成立
mysql> select name from user where id = 1 and name is null; # 有一方不成立
Empty set (0.00 sec)
mysql> insert into tarena.user(name,uid) values(null,2001)
mysql> select * from user where name is null ;
如果null加了双引号就变成字符串了,不表示空字符了。
mysql> insert into tarena.user(name,uid) values("null",2001)
mysql> insert into tarena.user(name,uid) values(" ",2001)
mysql> insert into tarena.user(name,uid) values("",2001)
mysql> select name ,shell from user
-> where
-> shell in ("/bin/bash","/sbin/nologin");
mysql> select name,uid from user where uid not in (1,2,3,21,12,312) ;
mysql> select name,id from user where id between 10 and 20 ;
mysql> select name from user where name like '____'; # 一个下划线表示一个字符
mysql> select name from user where name like '_%_'; # 表示至少是两个字符的 % 表示任意多个
mysql> select name from user where name like 'a%'; # 以a开头的
mysql> select name from user where name regexp '^a' ; # 正则 以a开头
mysql> select name from user where name regexp '^a.*t$'; # 正则 以a开头 以t 结尾
Empty set (0.00 sec)
筛选条件的写法
查找数据的时候有多个查找条件
逻辑与 and && 多个查找条件必须全部成立
逻辑或 or || 多个查询条件某个条件成立即可
逻辑非 not ! 取反
() 提高优先级别 (条件)
优先级 () and or
and 和 or 同时存在是先判断and再判断or
mysql> select name ,uid from user where name = "root" and uid = 1;
mysql> select name ,uid from user where name = 'root' or uid = 1;
mysql> select name ,uid from user
-> where
-> uid != 1 ;
mysql> select (2+2)*7 as 结果;
mysql> select name ,uid from user where name ='root' and uid =0 or uid =1;
mysql> select name ,uid from user where name = 'root' or name ='bin' and uid = 1;
mysql> select name ,uid from user
-> where
-> (name = 'root'or name = 'bin') and uid = 1;
表放在
[root@mysql1 ~]# ls /var/lib/mysql
auto.cnf client-key.pem ib_logfile1 mysql.sock.lock server-cert.pem
ca-key.pem ib_buffer_pool ibtmp1 performance_schema server-key.pem
ca.pem ibdata1 mysql private_key.pem sys
client-cert.pem ib_logfile0 mysql.sock public_key.pem tarena
[root@mysql1 ~]# cd /var/lib/mysql/tarena/
[root@mysql1 tarena]# ls
db.opt departments.ibd employees.ibd salary.ibd user.ibd
departments.frm employees.frm salary.frm user.frm
原有的四个库不能删除,
裤:存放表的目录
create database [if not exists] 数据库名
[] 表示可选项
mysql> create database game ;
mysql> show databases;
mysql> use game ;
Database changed
mysql> show tables;
Empty set (0.00 sec)
[root@mysql1 ~]# ls /var/lib/mysql
auto.cnf game ibtmp1 private_key.pem tarena
ca-key.pem ib_buffer_pool mysql public_key.pem
ca.pem ibdata1 mysql.sock server-cert.pem
client-cert.pem ib_logfile0 mysql.sock.lock server-key.pem
client-key.pem ib_logfile1 performance_schema sys
# 就多了一个game库
mysql> create database if not exists game ; # 假如库不存在的话,创建,存在不报错
Query OK, 1 row affected, 1 warning (0.00 sec)
库名:
删库
库文件下面的文件也会一并删除
mysql> show databases;
mysql> drop database buy;
mysql> drop database game;
mysql> show databases ;
mysql> drop database if exists game ; # 当库不存在的时候删除库,不会报错;
定义:就是定义存储数据的文件有哪些表头
比如 创建一张表存储学生信息
姓名 性别 年龄 班级 电话号码 住址 身份证号
建表的命令格式
create table 库名.表名(表头名 数据类型 , 表头名 数据类型);
每种类型都有规定好的命令表示
比如字符类型的数据 使用char
比如数字类型的数据 使用 int
create database studb ;
create table studb.stuinfo(name char(10),age int(2));
insert into studb.stuinfo values('jim' ,19),("tom",16);
select * from studb.stuinfo;
[root@mysql1 ~]# ls /var/lib/mysql/studb/
db.opt stuinfo.frm stuinfo.ibd
mysql> desc studb.stuinfo; 可以查看到表的结构;后面的4列是约束条件
[root@mysql1 ~]# ls /var/lib/mysql/tarena/salary.frm # 存放表的结构.frm
/var/lib/mysql/tarena/salary.frm
[root@mysql1 ~]# ls /var/lib/mysql/tarena/salary.ibd # 存放表的信息.ibd
/var/lib/mysql/tarena/salary.ibd
注意:表必须存放在库里
desc 库.表名; # 查看表结构
drop table 库.表名 # 删除表
提问1;建表时 如何确定表中应该有几个表头名 表头名都叫什么
E-R模型(标准)
提问2:如何判断好的表 是否创建的 合理?
建表范式(标准)
2NF与3NF的区别:
在于有没有分出2张表,2NF如果一张表中含有多种不同实体的属性那么必须要分成多张表。3NF已经分成多张表后,一张表中只能有另一张表中的主键,而不能有其他信息。
删除表中的数据
mysql> delete from studb.stuinfo; # 慎用
mysql> select * from studb.stuinfo;
使用studb.stuinfo表练习修改表结构
工作中是把表的结构修改好后,再存储数据的
delete from studb.stuinfo ; 删除表里的所有行
修改并表结构的命令格式:
alter table 库名.表明 操作命令‘
操作命令 | 说明 |
---|---|
add | 添加新字段,一起添加多个字段使用,分隔add命令(frist after) |
modify | 修改字段类型,也可以修改字段的位置 |
change | 修改字段名,也可以同时修改字段类型 |
rename | 修改表名 |
drop | 删除字段 删除多个字段使用 , 分隔drop命令 |
操作命令包括那些
add 表头名 数据类型 ,add 表头名 数据类型 ;
mysql> desc studb.stuinfo;
mysql> alter table studb.stuinfo add class char(7) ,add mail char(20);
mysql> desc studb.stuinfo;
mysql> alter table studb.stuinfo add 学号 int first ; # 在表第一列添加first
mysql> desc studb.stuinfo;
mysql> alter table studb.stuinfo add 住址 char(50) after name ; # 在name后面添加
mysql> desc studb.stuinfo;
drop 表头名
mysql> alter table studb.stuinfo drop 学号,drop 住址;
mysql> desc studb.stuinfo;
modify 表头名 数据类型 [约束条件];
mysql> desc studb.stuinfo;
mysql> alter table studb.stuinfo modify class varchar(10), modify mail varchar(30) not null default '[email protected]';
mysql> desc studb.stuinfo;
mysql> alter table studb.stuinfo modify class varchar(10) after name ;
mysql> desc studb.stuinfo;
change 源表头名 新表头名 数据类型 约束条件;
mysql> alter table studb.stuinfo change name 姓名 char(10);
mysql> desc studb.stuinfo;
如果想把数据类型和约束条件也修改的话,直接写新的数据类型和约束条件即可
mysql> alter table studb.stuinfo change mail 邮箱 char(50) not null default '163.com';
mysql> desc studb.stuinfo;
rename
mysql> alter table studb.stuinfo rename studb.学生信息表;
mysql> show tables ;
语法格式
仅复制表的结构
create table 库.表 select 列名 from 库.表 where 1=2;
仅复制表结构及数据
create table 库.表 select 列名 from 库.表 [where 条件]
create table studb.部门表 select * from tarena.department
mysql> desc studb.部门表;
注意: 原表的key,不会复制给新表,新表数据与select语句决定
仅复制表结构
create table 库.表 like 库.表
create table studb.部门表 like tarena.departments
mysql> desc studb.部门表2 ;
注意:原有的key 同时复制给新表
指定表使用中文字符集utf8 才可以给表存储汉字
create table studb.stuinfo2(姓名 char(10),住址 char(50),职业 char(5)) default charset utf8
mysql> create table studb.stuinfo2(姓名 char(10),住址 char(50),职业 char(5)) default charset utf8;
mysql> desc stuinfo2;
mysql> insert into stuinfo2 values("小奶狗","狗窝","运维汪");
mysql> insert into stuinfo2 values("小奶狗","狗窝","运维汪");
mysql> select * from stuinfo2;
mysql> show create table stuinfo2 \G
对表中的行做管理:包括
查询:select 查看表里已经存储的数据(最多)
插入:inster into 向表中添加新行
修改:update 修改行中列的值
删除记录 delete 把表中的行删除
mysql> select * from tarena.departments;
常用格式1
给所有表头赋值 值必须与表头的数据类型匹配
inert into 库. 表 values (表头值列表);
intert into 库. 表 values (表头值列表),(表头值列表); 一次添加多行
常用格式2
仅给指定的表头赋值,没有赋值的标头是有默认值或自增长赋值
insert into
mysql> insert into user values (30,'dc','x',666,666,'testuser','/home/dc','/sbin/nologin');
mysql> select * from user where id=30;
# 指定字段赋值
mysql> insert into user(name,id) values("john",888);
mysql> insert into user(name,uid) values("john1",888);
mysql> select * from user where uid=888;
# 使用查询结果存进记录
mysql> select name from user where shell = '/sbin/halt';
mysql> insert into user(name) (select name from user where shell = '/sbin/halt') ;
mysql> select name from user where name = 'halt';
# 使用set进行赋值
mysql> insert into user set name = 'dachui' ,uid = 999;
mysql> select * from user where name = 'dachui';
格式1
update 库. 表 set 字段名= 值,字段名= 值… where 筛选条件; 只修改符合条件的字段
类型匹配才能允许修改
格式2
update 库. 表 set 字段名= 值 ;批量修改
mysql> select name,comment,password from user where name="root";
mysql> update user set comment='admin user',password='a' where name ='root';
mysql> select name,comment,password from user where name="root";
mysql> update user set password= 'F';
mysql> select id,password from user ;
格式1:
delete from 库.表 where 筛选条件 ; 仅删除表中与条件匹配的行
格式2
delete from 库.表 ; # 谨慎,会将表中所有的数据删除
mysql> select * from user where shell is null ; # 删除前查看
mysql> delete from user where shell is null ;
mysql> select * from user where shell is null ; # 删除后查看
delete from user; # 慎用,删除所有的行
每种类型都有规定好的命令表示
比如字符类型char
mysql服务常用数据类型有;
数值类型 如 身高 体重 成绩
字符类型 如 地址 籍贯 姓名
枚举类型 如 爱好 性别 婚姻状况 (列举出来,给你选择的类型)set (多选) enum(单选)
日期时间类型 如 生日 上课时间 入职时间
类型 | 名称 | 有符号类型 | 无符号类型 |
---|---|---|---|
tinyint | 微小整数 | -128~127 | 0~255 |
smallint | 小整数 | -32768~32767 | 0~65535 |
medliumint | 中整数 | -223~223-1 | 0~2^24-1 |
int | 大整数 | -231~231-1 | 0~2^32-1 |
bigint | 极大整数 | -263~263-1 | 0~2^32-1 |
unsigned | 使用无符号存储范围 |
create table t3(姓名 char(10), 年龄 tinyint unsigned, 工资 float, 圆周率 double , 游戏级别 smallint);
mysql> desc t3;# 第二个值出现了负值,就出现错误了,因为表结构写了是正整数
mysql> insert into t3 values ("jim",256,205555.88,301415426, -1);# 在范围内,所以不会报错
mysql> insert into t3 values ("jim",25,205555.88,301415426, -1);
不能存负数的效果
mysql> desc t3;
mysql> insert into t3(姓名,年龄) values ('jon',-1);
mysql> insert into t3(姓名,年龄) values ('jon',0);
小数可以存整数和小数
整数只能存整数(四舍五入)
mysql> insert into t3(姓名,年龄,工资) values ('tom',19.5,55555 );
mysql> select * from t3 where 姓名= 'tom';
表头下存储英文字母 或 汉字
常用的字符类型有:
定长类型 char 最多存储255个字符,不写的话是默认4
变长类型 varchar 最多存储65532个字符 不写()的话,出现语法错误
定长:超出的话,报错,不够的话系统自动以空格补齐
变长:也是不能超出,长度是变化的,是根据存储的数量而定,不会补齐
mysql> create table t4(姓名 varchar(10), 班级 char(7) ,电话号码 char(11) ,邮箱 varchar(30) )default charset utf8;
mysql> desc t4;
# 没加引号
mysql> insert into t4 values('沙调',nsd2110,122212112,[email protected]);
mysql> insert into t4 values('沙调','nsd2110','122212112','[email protected]');
mysql> select * from t4;
其他字符类型 比如 大文本 二进制….
年 year 赋值 YYYY 例如 2022
日期 date 赋值YYYYMMDD 例如20220209
时间 time 赋值HHMMSS 例如223000 晚上十点半
日期时间 datetime 或 timestanp 赋值YYYYMMDDHHMMSS 例如20220209091618
# 创建表
mysql> create table studb.t1(name char(10),birthday date , work time , party datetime);
mysql> desc studb.t1;
mysql> alter table studb.t1 add start year after name;
mysql> insert into studb.t1 values("ds",20221120,090000,20220218183000);
mysql> desc studb.t1;
mysql> select * from studb.t1;
mysql> update studb.t1 set start = 2000 where name = 'ds';
mysql> select * from studb.t1
-> ;
year 数据类型的表头 可以使用2位数赋值,但是会自动补全4位数
01~69 2001-2069
70~99 1970-1999
mysql> insert into studb.t1(name,start) values ('jim',52);
mysql> select * from studb.t1 where name = 'jim';
mysql> insert into t1(name,start) values('hh',99);
mysql> select * from t1 where name = 'hh';
mysql> create table t2(开会时间 datetime , 聚会时间 timestamp);
mysql> insert into t2 values(20220209183000,20220212203000);
mysql> select * from t2;
# 没给timestamp赋值的话,会默认写入数据库系统时间去复制
mysql> insert into t2(开会时间) values(20180209183000);
mysql> select * from t2 ;
# 每给datetime赋值的话是NULL
mysql> insert into t2(聚会时间) values(20180202213000);
mysql> select * from t2;
对数据做批量处理
把系统文件的内容存储到数据库的表里
文件的必须是有规律的
数据导入的命令格式
load data infile ‘/目录名/文件名’ into table 库.表
fileds terminated by “符号(表头的间隔符号)”
lines terminated by “符号(行的间隔符号)” ;
在mysql登录状态先执行系统命令
system cp /etc/passwd /myload
# 先将文件复制到/myload目录下面
mysql> load data infile "/myload/passwd" into table studb.user
-> fields terminated by ":" lines terminated by "\n";
mysql> select * from studb.user ;
练习:
将/etc/passwd文件的内容存储到studb.user表里
create table user(
用户名 varchar(20),
密码 char(1),
uid int,
gid int,
说明信息 varchar(150),
家目录 varchar(100),
shell varchar(30)
);
mysql> desc user;
操作步骤:
检索目录(导入导出存放文件的目录)
mysql> show variables like "%file%";
mysql> show variables like "secure_file_priv";
[root@mysql1 ~]# ls /var/lib/mysql-files/
[root@mysql1 ~]# ll -d /var/lib/mysql-files/
drwxr-x--- 2 mysql mysql 6 11月 29 2016 /var/lib/mysql-files/
[root@mysql1 ~]# vim /etc/my.cnf
[mysqld]
secure_file_priv=/myload # 手动添加
#skip-grant-tables
validate_password_policy=0
validate_password_length=6
[root@mysql1 ~]# mkdir /myload
[root@mysql1 ~]# ls /myload/
# 使得mysql能有多这个文件有操作的能力
[root@mysql1 ~]# chown -R mysql:mysql /myload
# selinux 必须关闭
[root@mysql1 ~]# setenforce 0
setenforce: SELinux is disabled
[root@mysql1 ~]# systemctl restart mysqld
# 如果重启失败:配置文件可能写错,目录没有权限
# 再次登陆查看就可以看到文件已经修改了;说明修改成功
mysql> show variables like "secure_file_priv";
把数据库表里 存储到系统文件
说明
文件名不需要创建 会自动创建文件并存储数据文件名具有唯一性
导出数据的内容,由select命令决定
导出的只有内容,没有表头名
表里1条的记录 就是文件里的1行
# 格式1
mysql> select name ,hire_date,birth_date from tarena.employees limit 3;
mysql> select name ,hire_date,birth_date from tarena.employees limit 3 into outfile
-> "/myload/employees.text" ;
mysql> system cat /myload/employees.text
梁伟 2018-06-21 1971-08-19
郭岩 2010-03-21 1974-05-13
李玉英 2012-01-19 1974-01-25
# 格式2
mysql> select name ,hire_date,birth_date from tarena.employees limit 3
-> into outfile "/myload/employees.text1" fields terminated by ":";
Query OK, 3 rows affected (0.00 sec)
mysql> system cat /myload/employees.text1
梁伟:2018-06-21:1971-08-19
郭岩:2010-03-21:1974-05-13
李玉英:2012-01-19:1974-01-25
# 格式3
mysql> select name ,hire_date,birth_date from tarena.employees limit 3
-> into outfile "/myload/employees.text2"
-> fields terminated by ":"
-> lines terminated by "\t";
mysql> system cat /myload/employees.text2
梁伟:2018-06-21:1971-08-19 郭岩:2010-03-21:1974-05-13 李玉英:2012-01-19:1974-01-25
所用;限制如下给表头存储数据
查看字段约束: desc 库.表;输出结果的后4列统称为约束字段
mysql> desc user;
NULL :空
Key:键值
default:默认值
Extra:额外设置
基本的字段约束
不允许给表头存储null(默认是允许的)
create table t5(name char(10) not null ,class char(7));
mysql> create table t5(name char(10) not null ,class char(7));
mysql> desc t5;
# name添加的时候就不能再设置为空值了
mysql> insert into t5 values(null.null);
# 只有class可以为null
mysql> insert into t5 values ("ii",null);
给表头设置默认
什么是默认值 添加记录时 不给表头存储数据 使用默认值赋值
默认值要与表头的数据类型一致
mysql> create table t6(name char(3) not null , class char(7) default'nsd2110',sex enum('w','m') not null default 'm');
mysql> desc t6;
mysql> insert into t6(name) values ('jj');
mysql> select * from t6;
mysql> insert into t6 values ('hh',"nn111","w");
mysql> select * from t6 where name = 'hh';
唯一索引 unique
所用:表头下的数据不能重复
例如:身份证号码 、护照号、证书编号
所有存放证件信息的数据都是不能重复
mysql> create table t7(
-> 学号 char(9),name char(10),age tinyint unsigned default 21,unique(学号));
mysql> desc t7;
# unsigned 表示无字符
mysql> insert into t7 values("nsd211011","jim",29);
# 学号是唯一索引,不允许重复,所以会报错。
mysql> insert into t7 values("nsd211011","tom",19);
# 空不算重复,没有数据不涉及到重复
4. 主键 primary ley
- 表头下的数据 即不能重复 也不能允许赋予null值
- ```mysql
mysql> create table t8(
-> 身份证 char(18),
-> 姓名 char(4),primary key(身份证)
-> );
# 没有设置not null 设置了primary key,自动设置为不能为null
# 主要是有key PRI 都是不能允许重复,也不允许赋予null值
mysql> desc t8;
mysql> insert into t8 values('888','jim');
# 不能重复
mysql> insert into t8 values('888','tom');
# 不能为空
mysql> insert into t8 values(null,'hh');
```
- 删除主键
```mysql
mysql> desc t8;
mysql> alter table t8 drop primary key;
# 删除主键之后就可以插入相同的'身份证‘记录
mysql> insert into t8 values('888','dsa');
给表头添加主键约束(表头下存储的数据不满组主键时 主键添加不上)就是如果有重复或者是为空的表头值 就添加不上primary key
mysql> alter table t8 add primary key(身份证);
解决方案是删除或者修改记录
复合主键
什么是复合主键:多个表头一起做主键
约束的方式 :不允许复合主键表头的值同时重复
mysql> create table t9(ip varchar(15) ,prot int ,status enum("allow","deny"),primary key(ip,prot));
mysql> desc t9;
mysql> insert into t9 values('1111',22,'deny');
mysql> insert into t9 values ('2111',22,'allow');
mysql> insert into t9 values('2111',80,'allow');
mysql> select * from t9;
删除表的复合主键
mysql> alter table t9 drop primary key;
mysql> desc t9;
删除复合主键
mysql> alter table t9 add primary key(ip,prot);
mysql> desc t9 ;
主键与auto_increment 连用
auto_increment的作用: 不给表头赋值时候 是自加1 的计算结果给表头赋值
注意:给表头加auto_increment设置,表头的数据类型必须是数值类型的
mysql> create table t10(id int primary key auto_increment, name char(10),age int ,class char(7),socr int );
mysql> desc t10;
mysql> insert into t10 (name ,age ,class ,socr) values ('a',19,'2111',93);
mysql> select * from t10;
mysql> insert into t10 (name ,age ,class ,socr) values ('b',12,'123',456);
mysql> select * from t10 ;
自增长的扩展
mysql> truncate t10;
mysql> select * from t10 ;
mysql> insert into t10 (name ,age ,class ,socr) values ('b',12,'123',456);
mysql> select * from t10;
# truncate 不支持where条件
# 自增长列,truncate后从1开始;delete继续编号(继上次的编号)
# truncate不能回滚,delete可以
# 效率略高于delete
复制表 不会复制 主键和 自增长的
使用规则
使用规则
创建外键
命令格式
create table 库.表 (表头名列表, foreign key(表头名) references 库名.表名(表头名)
on update cascade on delete cascade
) engine=innodb;
on update cascade : 同步更新
on delete cascade: 同步删除
# 在员工表中没有199的id,所以添加不上,因为外键限制了
mysql> insert into salary (date,employee_id ,basic ,bonus)
-> values
-> (20220809,199,30000,2000);
mysql> insert into salary (date,employee_id ,basic ,bonus)
-> values
-> (20220809,8,30000,2000);
mysql> desc salary;
mysql> create table yg_tab(yg_id int primary key auto_increment,name char(5))engine=innodb;
mysql> insert into yg_tab(name) values ('dc'),('hh');
mysql> select * from yg_tab;
mysql> desc yg_tab;
mysql> create table gz_tab(gz_id int ,pay int,foreign key(gz_id) references yg_tab(yg_id) on update cascade on delete cascade )engine=innodb;
mysql> desc gz_tab;
验证外键的
mysql> select * from yg_tab;
# 在里面没有3 的编号 # 在外键表头名添加数据的时候必须要符合
mysql> insert into gz_tab values (3,3000);
# 在符合外键的要求之下就可以添加了。
mysql> insert into gz_tab values (1,121313);
mysql> select * from gz_tab;
mysql> insert into yg_tab(name) values ('lili');
mysql> select * from yg_tab ;
mysql> insert gz_tab values (3,456);
mysql> select * from gz_tab;
验证 on update cascade
mysql> update yg_tab set yg_id = 8 where yg_id = 3;
mysql> select * from yg_tab;
# 由于添加了on update cascade 所以在修改yg_tab的时候gz_tab也会自动修改
mysql> select * from gz_tab;
验证 on delete cascade
mysql> delete from yg_tab where yg_id=2;
mysql> select * from yg_tab;
mysql> select * from gz_tab;
外键的使用扩展
mysql> alter table gz_tab add primary key(gz_id);
mysql> desc gz_tab;
# 设置主键之后避免出现重复发工资
查看外键
mysql> show create table gz_tab \G
删除外键
mysql> alter table gz_tab drop foreign key gz_tab_ibfk_1;
# 删除外键之后就没有了 gz_tab_ibfk_1
mysql> show create table gz_tab \G
添加外键
mysql> alter table gz_tab add foreign key(gz_id)
-> references yg_tab(yg_id)
-> on update cascade on delete cascade ;
mysql> show create table gz_tab \G
*************************** 1. row ***************************
表里的行比较少或表里的列有重复数据的时候不建议使用
经常修改表的话,也不建议使用索引,这会大大降低服务器的性能
加快查询数据的速度
具体操作
普通索引(index):工作中使用最多
唯一索引
全文索引 fulltext
单列索引
多列索引
查看 desc 库.表 ;
输出的信息中key列的值是MUI
mysql> desc tarena.employees;
# 查看表里的索引
mysql> show index from tarena.employees \G
创建
建表时给表设置排队索引
mysql> create table t1(name char(10) ,class char(11), addr char(20),age int ,index(name),index(addr));
mysql> show index from t1 \G
删除
d
mysql> drop index name on t1 ;
mysql> desc t1;
添加
添加索引
mysql> create index name on t1(name);
mysql> desc t1;
mysql> create index iiii on t1(age);
mysql> desc t1;
mysql> show index from t1 \G
# Key_name : 表头的索引名
# Column_name : 这个是表头名
外键没有去掉,是删除不了索引
通常把做查询条件的表头 添加索引标记 可以加快查询数据的速度
mysql> select * from user where 用户名 = 'halt';
mysql> 这个是从第一行开始找^C
mysql> 想知道是怎么查的,知道怎么查的在命令面前加上explain^C
mysql> explain select * from user where 用户名 = 'halt';
# 得知搜索了22行的数据
# Using where 是使用了where命令查找了表里记录
添加了索引之后
mysql> create index 用户名 on user(用户名);
# 添加索引之后再次查找的话先去找索引,再去找表里的记录,类似与书的目录。
mysql> explain select * from user where 用户名 = 'halt';
# rows 这里就是直接在表里查找的多少行
explain可以检查查询有没有使用到索引,具体有没有使用索引看keys下面有没有索引名称
生成排队信息的是查询的时候先访问排队文件中先去找,不是在表中直接找
说明
语法格式
添加新用户的命令格式
create user 用户名@“客户端地址” indentified by ”密码“ with grant option ;
mysql> create user zhangsan@'%' identified by '123456';
mysql -h192.168.4.50 -uzhangsan -p123456
mysql> select user(); # 查看远程登录的用户
mysql> select user();
授权命令格式:
格式1(创建用户并设置权限)
grant 权限列表 on 数据库名 to 用户名 @“客户端地址” identified by “密码” with grant option
格式2
grant 权限列表 on 数据库名 to 用户名 @“客户端地址”
# 查看所有的权限
mysql> show grants;
# 给zhangsan用户添加select权限对tarena.user的操作
mysql> grant user on studb to zhangsan@'%' identified by '123456'^C
mysql> grant select on tarena.user to zhangsan@'%';
mysql> grant all on . to yaya@‘192.168.4.%’ identified by ‘123456’ with grant option ;
Query OK, 0 rows affected, 1 warning (0.00 sec)
参数说明
权限说明
授权库(指的是mysql库)
grant命令 的执行对mysql下面的表的操作
例子
grant select,update(name,uid) on studb.user to hh@'localhost' identified by '123456';
select 是对所有表头都有查询的权限
update 只对name,uid 有修改的权限
select * from mysql.tables_priv
desc mysql.tables_priv
select host,user,db,table-name from mysql.tables_priv
select * from mysql.tables_priv where user = hh;
desc mysql.columns_priv
select * from msyql.columns_priv where user = hh;
show grants for hh@'localhost';
update mysql.tables_priv set Tables_priv = "select,delete" where user = 'hh';
flush privileges;
show grants for hh@'localhost';
update mysql.columns_priv set Column_name = "name" where user = 'hh';
flush privileges;
show grants for hh@'localhost'
mysql> select host ,user from mysql.user;
# 查看用户的密码
mysql> select host,user ,authentication_string from mysql.user;
mysql> set password for admin@'192.168.4.51'=password("NSD2110...a");
Query OK, 0 rows affected, 1 warning (0.00 sec)
# 修改之后也是以加密的方式存储进mysql.user里面
mysql> show grants for zhangsan@'%';
在设置有这个命令的用户下面,创建可以创建用户,最大权限是创建主的最大权限
语法格式
相关命令
命令 | 作用 |
---|---|
select user(); | 显示登录用户名及客户端地址 |
show grants; | 用户显示自身访问权限 |
show grants for 用户名@’客户端地址‘; | 管理员查看已有授权用户权限 |
set password=password(“密码”); | 授权用户连接后修改连接密码 |
set password for 用户名@“客户端地址” = password(“密码”); | 管理员重置授权用户连接密码 |
drop user 用户名@’客户端地址‘; | 删除授权用户(必须有管理员权限) |
rename user 原用户名 to 新用户名 | 修改用户名 |
mysql> select user();
mysql> select now();
password()
这个函数就要添加参数了eg:password('aaa')
函数查询的基本格式
select 函数(字段名) from 库名
作用:处理字符或字符类型的字段
函数名称 | 说明 |
---|---|
length(str) | 返回字符串长度,以字节为单位 |
char_length(str) | 返回字符串长度,以字母为单位 |
upper(str)和ucase(str) | 将字符串中的字母全部换成大写 |
lower(str)和 lcase(str) | 将str中的字母全部换成小写 |
substr(s,start,end) | 从s的start位置开始取出到end长度的字串 |
instr(str,str1) | 返回str1参数,在str参数内的位置 |
trim(s) | 返回字符串s删除了两边空格之后的字符串 |
select name,length(name),stubstr(name,1,1),instr(name,’a’) from tarena.user where name regexp ‘a’;
作用:处理数据或数据类型的字段
函数名 | 说明 |
---|---|
abs(x) | 返回x的绝对值 |
pi() | 返回圆周率,默认显示6位小数 |
mod(x,y) | 返回x被y除后的余数 |
gril(x)、ceiling(x) | 返回不小于x的最小整数(x是小数) |
floor(x) | 返回不大于x的最大整数(x是小数) |
round(x) | 返回最接近于x的整数,即对x进行四舍五入(x是小数) |
round(x,y) | 返回最接近x的数,其值保留小数点后面y位,若y为负值,则将保留到x到小数点左边y位(x是小数) |
select name ,uid from tarena.user where mod(uid,2)=0;
作用:数据统计命令
函数名 | 说明 |
---|---|
avg(字段名) | 计算平均值 |
sum(字段名) | 求和 |
min(字段名) | 获取最小值 |
max(字段名) | 获取最大值 |
count(字段名) | 统计字段值个数 |
select count(*) from tarena.user;
符号 | 用途 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取余数(求模) |
() | 提高优先级 |
select name ,uid ,uid+1,gid,uid+gid,(uid+gid) from tarena.user where id%2 !=0;
作用:获取系统或指定的时间与日期
函数 | 说明 | 函数 | 说明 |
---|---|---|---|
curtime() | 获取时间 | hour() | 获取小时 |
curdate() | 获取日期 | minute() | 获取分钟 |
now() | 获取时间和日期 | second() | 获取秒 |
year() | 获取年 | quarter() | 获取一年中第几个季度 |
month() | 获取月 | monthname() | 获取月份名称 |
day()/week() | 获取日/一年中的第几周 | datname() | 获取日期对应的星期名 |
date()/weekday() | 获取日期/一周中的周几 | dayofyear() | 获取一年中第几天 |
time() | 获取时间 | dayofmonth() | 获取一月中第几天 |
语法:
if(条件1,v1,v2) 如果条件是true则返回v1,否则返回v2
ifnull(v1,v2) 如果v1不为null,则返回v1,否则返回v2
select name,uid,if(uid<1000,”系统用户“,”创建用户“) from tarena.user
select name,shell,if(shell=“/bin/bash”,”交互账号”,”非交互账号”) from tarena.user;
insert into tarena.user(name,homedir) values(“bob”,”NULL);
select name 姓名 ,ifnull(homedir,”no home”) as 家目录 from tarena.user;
例子
mysql> select ifnull(null,"abc");
mysql> select ifnull("abc","aaa");
mysql> select name ,ifnull(shell,"NULL") from user;
语法;如果字段名等于某个值,则返回对应位置then后面的结果,如果与所有值都不相等,则返回else后面的结果
是if()函数扩展 case可以有多个判断
case 字段名
when 值1 then 结果
when 值2 then 结果
when 值3 then 结果
else 结果
end
- 例子
```mysql
mysql> select name ,shell,
-> case shell
-> when "/bin/bash" then "yes login"
-> when "/sbin/nologin" then "no login"
-> else "other shell"
-> end as 登录类型
-> from tarena.user ;
+-----------------+----------------+--------------+
| name | shell | 登录类型 |
+-----------------+----------------+--------------+
| root | /bin/bash | yes login |
| bin | /sbin/nologin | no login |
| daemon | /sbin/nologin | no login |
| rpcuser | /sbin/nologin | no login |
| nfsnobody | /sbin/nologin | no login |
| haproxy | /sbin/nologin | no login |
+-----------------+----------------+--------------+
23 rows in set (0.01 sec)
mysql> select dept_name ,case dept_name
-> when "运维部" then "技术部门"
-> when "开发部" then "技术部门"
-> when "测试部" then "技术部门"
-> else "非技术部门"
-> end as 部门类型
-> from departments;
# 格式2
select dept_name ,case
when dept_name="运维部" then "技术部门"
when dept_name="开发部" then "技术部门"
when dept_name="测试部" then "技术部门"
else "非技术部门"
end as 部门类型
from departments;
语法:
说明:
例子
# 会报错
select name ,shell from user group by shell ; # 没有单独使用
select name from user group by shell; # 没有单独使用,搜索的字段没有在组里
# 单独使用,或与聚集函数一起使用
select count(name ) ,shell from user group by shell ;
select shell from user group by shell ;
# 使用每种shell 的用户有几个
select count(name) ,dept_id from employees where dept_id = 1 group by dept_id ;
select count(name) ,dept_id from employees group by dept_id having dept_id = 1 ;
select count(name) ,dept_id from employees group by dept_id limit 1;
语法:
select 语句 order by字段名 【asc|desc】
asc 升序排序(默认)
desc 降序排序
表头 是数据类型的表头
例子:
select name ,uid from user where uid between 10 and 100 order by uid ;
select name ,uid from user where uid between 10 and 100 order by uid desc ;
作用:对查询到的数据做筛选
语句:sql语句 having 条件;
在select命令 查询结果里再查找符合条件的数据
例子
select * from salary where basic between 21000 and 30000 having employee_id = 7 limit 5;
select * from salary where basic between 21000 and 30000 having employee_id = 7;
作用:限制查询结果显示行数(默认显示全部的查询结果)
语法:
例子
select name ,uid from user where uid between 10 and 100 limit 4;
select name ,uid from user where uid between 10 and 100 limit 0,10;
select name,uid from user where uid between 10 and 100 order by uid limit 1 ;
按功能分类
按年代分类
SQL92标准:支持内连接
SQL99标准;支持所功能的连接
SQL99标准多表查询
select 字段列表
from 表1【as】 别名 【连接类型】
join 表2 【as】 别名
on 连接条件
where 分组前筛选条件
group by 分组
having 分组后筛选条件
order by 排序字段
连接查询时候给表头起别名
不知道显示那个表里dept_id 表头是那个表的值的时候
语法格式 : inner join …on…
select 字段列表
from 表1 别名
inner join 表2 别名 on 连接条件
inner join 表3 别名 on 连接条件
【where 筛选条件】
【group by 分组】
【having 分组后筛选】
【order by 排序列表】
根据筛选条件分类:
例子
-- 等值连接
select name ,employee_id ,dept_name from employees a inner join departments b on a.dept_id = b.dept_id where employee_id =8;
select name,basic+bonus,date from salary s inner join employees e on s.employee_id = e.employee_id where e.employee_id = 11 and year(date) = 2018;
找出2018每个人的总工资的
select e.employee_id ,sum(basic+bonus) 总工资 from employees e inner join salary s on e.employee_id = s.employee_id where year(date)=2018 group by employee_id order by employee_id limit 4;
2018年总工资并且大于30万的员工
输出的结果按照工资降序排序
select e.employee_id ,sum(basic+bonus) 总工资 from employees e inner join salary s on e.employee_id = s.employee_id where year(date)=2018 group by e.employee_id having 总工资 > 300000 order by employee_id ;
-- 非等值连接
-- 环境准备
create table wage_grade(id int primary key auto_increment,grade char(1) , low int , high int ) ;
insert into wage_grade(grade ,low,high) values('A','5000',8000),('B',8001,10000),('C',10001,15000),('D',15001,20000),('E',20001,100000);
-- 查看2018年12月份员工基本工资级别
select basic,grade,date from salary inner join wage_grade on basic between low and high where year(date) = 2018 and month(date) = 12;
-- 查看2018年12月份基本工资级别的员工个数
select count(employee_id),grade from salary inner join wage_grade on basic between low and high where year(date) = 2018 and month(date) = 12 group by grade;
-- 查看2018年12员工基本工资级别,员工需要显示姓名
select name,date ,basic ,grade from
employees e inner join salary s on e.employee_id = s.employee_id
inner join wage_grade g on s.basic between g.low and g.high
where year(date) = 2018 and month(date) = 12 order by grade;
-- 内连接(查看入职月份与生日的月份相同的)
select a.name,a.hire_date ,b.birth_date from employees a inner join employees b on month(a.hire_date)=month(b.birth_date) and a.employee_id =b.employee_id;
-- 不用内连接也可以查询
select * from employees where month(hire_date)=month(birth_date);
分类如下
例子
-- 向部门里面添加3个部门 行政部 小卖部 公关部
insert into departments(dept_name) values ('行政部'),('小卖部'),('公关部');
--
insert into employees(name) values ('bob'),('tom'),('lily');
-- 把没有员工的部门名称输出
select name,d.dept_id from employees e left join departments d on e.dept_id = d.dept_id where d.dept_id is null;
select d.*,e.name from employees e left join departments d on e.dept_id = d.dept_id where d.dept_name is null ;
select d.*,e.name from employees e right join departments d on e.dept_id = d.dept_id where name is null ;
select d.dept_name from employees e right join departments d on e.dept_id = d.dept_id where name is null ;
select d.dept_name ,e.name from departments d left join employees e on d.dept_id = e.dept_id ;
-- 仅仅是把没有的员工部门查找出来
select dept_name from departments d left join employees e on d.dept_id = e.dept_id where name is null;
-- 仅仅是把没有部门的员工名称打印出来
select name from departments d right join employees e on d.dept_id = e.dept_id where dept_name is null;
说明
语法格式
例子
select name ,birth_date from employees where year(birth_date)=1972 or year(birth_date ) >2000;
(select name ,birth_date from employees where year(birth_date)=1972) union (select name ,birth_date from employees where year(birth_date ) >2000);
select min(uid) from user;
select max(uid) from user ;
select min(uid),max(uid) from user ;
(select min(uid) from user)union (select max(uid) from user);
也叫嵌套查询(俄罗斯套娃)
通常是把内部查询语句的输出数据作为外层查询语句的查询条件
介绍
子查询长出现的位置
命令格式
例子
-- 查询运维所有员工信息
-- 分析 运功信息 只存储在employees表 但没有 部门名称 dept_name 表头 只有部门编号dept_id表头
select dept_id from departments where dept_name = "运维部"
select * from employees where dept_id =3
select * from employees where dept_id = (select dept_id from departments where dept_name = '运维部') ;
select * from employees e inner join departments d on e.dept_id = d.dept_id where dept_name = "运维部";
-- 查询2018年12月所有比100号员工基本工资高的工资信息
-- 查询2018年12月 比100号员工基本工资高 工资信息
year(date)= 2018 and month(date) = 12
select * from salary
select basic from salary where year(date)= 2018 and month(date) = 12 and employee_id = 100;
select employee_id,basic ,date from salary where year(date)= 2018 and month(date) = 12 and basic > (select basic from salary where year(date)= 2018 and month(date) = 12 and employee_id = 100);
select name ,basic ,date from salary s inner join employees e on e.employee_id = s.employee_id where year(date)= 2018 and month(date) = 12 and basic > (select basic from salary where year(date)= 2018 and month(date) = 12 and employee_id = 100);
-- 查询部门员工人数 比 开发部门人数少的部门
-- 查找的部门员工人数 条件是 比开发部门人数少的
select dept_id from departments where dept_name = '开发部'
select count(name) from employees where dept_id = 4;
select count(*) 人数,dept_id from employees group by dept_id having count(name) < 6;
-- 只查询出来少于开发部门的人数
select count(*) 人数,dept_id from employees group by dept_id having count(name) < (select count(name) from employees where dept_id = (select dept_id from departments where dept_name = '开发部'));
-- 使用内连接加上限制部门名字
select count(*) 人数,dept_name from employees e inner join departments d on e.dept_id = d.dept_id group by e.dept_id having count(name) < (select count(name) from employees where dept_id = (select dept_id from departments where dept_name = '开发部'));
-- 查看每个部门的人数
select count(*) 人数,dept_name from employees e inner join departments d on e.dept_id = d.dept_id group by e.dept_id
-- 自己写的
select count(employee_id) from employees group by dept_id;
select dept_name, (select count(employee_id) from employees e where d.dept_id = e.dept_id) r from departments d ;
-- 课程写的
select d.* ,(select count(employee_id) from employees e where e.dept_id = d.dept_id) 总人数 from departments d;
-- 查询认识部门和财务部门员工的信息
-- 查看人数部门和财务部门的 部门id
select dept_id from departments where dept_name = '人事部' or dept_name = '财务部';
select dept_id ,name from employees where dept_id in (1,2);
select * from employees where dept_id in (select dept_id from departments where dept_name = '人事部' or dept_name = '财务部');
-- 查询认识部2018年12月所有员工的工资
year(date)= 2018 and month(date) = 12
select * from salary where year(date)= 2018 and month(date) = 12
and employee_id in (select employee_id from employees where dept_id =
(select dept_id from departments where dept_name = '人事部'));
select id,date,basic,bonus,name from salary s inner join employees e on e.employee_id = s.employee_id where year(date)= 2018 and month(date) = 12
and s.employee_id in (select employee_id from employees where dept_id =
(select dept_id from departments where dept_name = '人事部'));
-- 查询2018年12月基本工资和奖金都是最高的工资信息
select max(basic) from salary where year(date)= 2018 and month(date) = 12;
select max(bonus) from salary where year(date)= 2018 and month(date) = 12;
select * from salary where year(date)= 2018 and month(date) = 12 and basic =(select max(basic) from salary where year(date)= 2018 and month(date) = 12) and bonus = (select max(bonus) from salary where year(date)= 2018 and month(date) = 12);
-- 添加了内连接的
select id,date,basic,bonus,name from salary s inner join employees e on e.employee_id = s.employee_id where year(date)= 2018 and month(date) = 12 and basic =(select max(basic) from salary where year(date)= 2018 and month(date) = 12) and bonus = (select max(bonus) from salary where year(date)= 2018 and month(date) = 12);
-- 查询3好部门及其部门内 员工的编号、名字和email
select employee_id ,name ,email from employees where dept_id = 3;
-- 同时需要显示部门名称
select dept_id ,dept_name ,employee_id ,name ,email from ( select d.dept_name ,e.* from departments d inner join employees e on d.dept_id = e.dept_id ) tmp_table where dept_id = 3 ;
就是执行1条命令可以修改或删除多张表里 的数据
多表更新
update 表1 as 别名
inner | left | right join 表2 AS 别名
on 连接条件
set 列=值 ,列=值....
[where 筛选条件]
多表删除
delete 表1 别名,表2 别名
from 表1 as 表1 别名
inner | left | right join 表2 as 表2 别名
on 连接条件
[where 筛选条件]
例子
create table t3 as select name ,uid from user limit 2;
create table t4 as select uid ,homedir ,shell from user limit 4;
select * from t3 inner join t4 on t3.uid=t4.uid ;
update t3 inner join t4 on t3.uid = t4.uid set t3.uid = 101 ,t4.uid = 102 where t3.name = 'bin' ;
select * from t3 ;
select * from t4;
select * from t3 inner join t4 on t3.uid = t4.uid;
delete t3,t4 from t3 inner join t4 on t3.uid = t4.uid ;
select * from t3 ;
select * from t4;
视图:是只有表头的表 数据是存放创建视图时 使用的物理表
什么是物理表:既有表头又有数据的表
视图是什么?
语法格式(需要牢记)
例子
create view vdb.v1 as select host ,user from mysql.user limit 3;
drop table vdb.v1; # 第一中删除,是删除不了视图的
drop view vdb.v1; # 第二种 才是删除视图的方式
create view v1 as select name ,uid ,shell from user ;
create view v2(姓名,家目录, 登陆状态) as select name, homedir,shell from tarena.user ;
# 说明了创建视图是可以使用连接查询的
create view v3 as select name ,email ,dept_name from employees e inner join departments d on e.dept_id = d.dept_id ;
# 查看一个库里面有那些视图 就描述信息里面有view是视图
show table status where comment = "view" \G
# 查看库下所有的表的状态信息
show table status \G
# 怎么知道视图的元数据在那里
show create view v2 \G
# 查看视图的
select * from v1 where name = 'root ';
# 修改视图的数据
update v1 set uid = 2088 where name ='root ';
# 再去查看元数据的表
select * from tarena.user where name = 'root ';
# 删除视图中的数据
delete from vi where name = 'root '
# 再去查看元数据的表,发现没有数据了
select * from tarena.user where name = 'root ';
# 直接去元数据的表添加数据,
insert into tarena.user(name ,uid ,gid ,homedir ) values ('yaya',888,888,"/home/yaya");
# 直接去视图查看数据
select * from v1 where name = 'yaya';
完成语法格式
create [or replace ]
[algorithm = { undefined | merge | temptable}]
[definer = { user | current_user }]
[sql securiy {definr | invoker }]
view view_name[(column_list)]
as select_statement
[with[cascaded | local] check option]
# 进阶的开始,前提
craete view v2 as select date, employee_id ,basic from tarena.salary where employee_id between 1 and 10 and year(date) = 2018 and month(date)=10;
update v2 set basic = 40000 where employee_id =1 ;
select date, employee_id ,basic from tarena.salary where employee_id = 1 and year(date) = 2018 and month(date)=10;
# 设置限制范围
# 1.视图的修改
create table t1 select name ,uid from tarena.user limit 3;
create table t2 select name ,uid from tarena.user limit 5;
-- 有重名,需要设置别名(说明创建视图的时候,表头名是不允许重复的)
create view v3 as select t1.namne as username ,t2.name as 姓名 from t1 inner join t2 on t1.name = t2.name ;
select * from v3;
-- 覆盖视图(如果不加上or replace 的话,已经重名的会报错的,加上的话,就会直接覆盖上去,相当于修改的效果了)
create or replace view v4 as select name ,uid ,gid from tarena.user
-- 支持检查选项(选项 local 满足自身的限制,同时要满足基本的限制)
-- with check option (支持检查选项)
-- 选项 local 满足自身的限制,同时要满足基本的限制
-- 选项 cascaded (默认值) 满足视图自身限制即可
-- 没有加上with check option的,就是没有做修改限制的,
create view tarena.v21 as select name ,uid from tarena.user where uid > 10 ;
update tarena.v21 set uid = 9 where name = 'games ' -- 说明了可以修改,但是再次查看试图的话,就没有查到games了,因为满足不了生成视图的条件了,所以显示不了
select * from tarena.user where name = 'games ' -- 发现uid变成了9
-- 覆盖创建
create or replace view tarena.v21 as select name ,uid from tarena.user where uid > 10 with check option ; -- 满足自身条件的限制是 uid > 10
update tarena.v21 set uid = 9 where name = 'games ' -- 再修改的话,会发现不满足条件
select * from tarena.v21 where name ='zzz'
update tarena.v21 set uid = 3 where name = 'zzz'; -- 虽然没有满足用户,但是视图没有满足修改,所以就不会报错
-- local 创建的
create view v31 as select name ,uid from tarena.user where uid <= 100 ;
create view v41 as select name ,uid from v31 where uid >=10 with local check option;
-- 现在去修改v41的视图的话需要满足 大于10 并且小于100,但是修改的话大于100 的话,是可以的,因为v31里面的没有 with check option,如果要达到上面的效果的话,需要
create or replace view v31 as select name ,uid from tarena.user where uid <= 100 with check option ;
show create view v31;
show create view v41;
select * from tarena.v41;
update tarena.v41 set uid = 9 where name = 'nobody'; -- 没有满足自身限制
update tarena.v41 set uid = 200 where name = 'games'; -- 没有满足基表v31限制
update tarena.v41 set uid = 55 where name = 'games'; -- 既满足自身限制,又满足v31限制
语法格式
delimiter //
create procedure 名称(参数列表)
begin
一组合法的sql命令
end
// 结束存储过程
delimiter;
delimiter 制定命令结束符号
mysql默认以";" 为分隔符,没有声明分隔符,编译会存储过程当成sql语句进行处理,则存储过程的编译过程会报错,所以需要加上delimiter 改为结束符号为//
说明:存储过程 是代码 不是表 归属于某个库如果存储过程没有参数()可以省略
例子
select count(*) from user ;
delimiter //
select count(*) from user //
delimiter ;
select count(*) from user ;
-- 创建存储的过程
delimiter //
create procedure tarena.p1()
begin
select count(*) from tarena.user ;
select count(*) from tarena.employees ;
select count(*) from tarena.salary ;
end //
delimiter ;
call tarena.p1;
call tarena.p1(); -- 执行存储脚本
drop procedure tarena.p1; -- 删除存储过程
查看存储的过程
执行存储过程
删除存储过程
例子
-- 存储过程是代码 不是表 归属与某个库
-- 存储过程的代码是保存在库下的表里
use tarena
show procedure status ; -- 只有type是procedure才是存储过程
-- 想看那个库的存储过程就需要先进库
-- 查看存储在表里的记录
use mysql;
desc proc \G -- 存放存储过程的表
select db,name,type from mysql.proc where name = "存储过程名字" ;
select db,name,type from mysql.proc where type='procedure';
-- 查看自定义的存储过程
select db,name,type from mysql.proc where type='procedure' and name = "存储过程名字" ;
-- 查看代码
select body,db,name,type from mysql.proc where type='procedure' and name = 'p1'; -- body标头是放代码的地方
全局变量( mysql读物运行后定义的变量 变量值 根据运行环境赋值)
会话变量
例子
-- 查看全局变量
show global variables ;
-- 例子
show global variables like "%password%" ;
show global variables like "%time%" ;
show global variables like "%file%" ;
show global variables like "%version%" ;
-- 修改变量
set global
set global validate_password_length = '值'
-- 输出全局变量的值
select @@变量名
select @@version ,@@version_comment;
-- 会话变量(根据当前登录数据库服务的用户产生的变量)
-- 会话变量的值有一部分和全局变量一样
-- 查看所有会话变量
show session variables ;
-- 例子
show session variables like "%timeout%";
show session variables like 'connect_timeout';
-- 修改会话变量
show session variables like "%buffer%"
set session sort_buffer_size=400000; -- 仅仅修改当前登录数据库的用户的会话变量
show session variables like 'sort_buffer_size';
-- 输出会话变量的值
select @@sort_buffer_size;
局部变量 只能用在begin/end语句块中
用户变量
例子
--
set @name = 'bob';
set @name = 'bob' , @birth = '2022-11-22';
select @name,@birth;
-- 断开之后再连接的话就会发现没有这变量了
select @name ; -- 返回的值就是null了
select @name,@birth
-- 把查询结果赋予变量
select count(name) from tarena.user where shel;='/bin/bash';
select count(name) into @user_num from tarena.user where shell='/bin/bash';
select @user_num;
-- 变量名重复时候,是被覆盖的,变量名是不可以使用中文的
select count(*) into @user_num from mysql.user ; -- 这样上面的变量名字就重复,所用到的值就会被覆盖
select @user_num;
-- 局部变量: 只能定义在begin和end 之间
-- 并且只在存储过程执行中有效 存储过程执行结束 局部变量会消失
declare 变量 类型
declare name char(10)
declare 变量 数据类型 default 值;
declare class char(7) default 'nsd2110'
-- 给局部变量赋值
set 变量名= 值 ;
declare age int; -- 只定义了变量
set age = 21 ; -- 给变量赋值
-- 局部变量使用的例子
delimiter //
create procedure tarena.o2()
begin
declare x int default 9;
declare y char(10);
set y = 'bob';
select x,y;
set x = 89;
select x,y;
end //
delimiter ;
select body from mysql.proc where name ='o2'; -- 查询存储过程密码
call tarena.o2 ;
drop procedure tarena.o2;
### 存储过程参数
- 调用参数时,名称前也不需要加@
- create procedure 名称 (类型 变量名 数据类型 ,类型 变量名 数据类型,。。。。)
- | 命令 | 类型 | 作用 |
| ----- | --------- | :----------------------------------------------------------: |
| int | 输入 | 给存储过程传值,必须在调用存储过程时赋值,在存储过程中该参数的值不允许修改(默认类型) |
| out | 输出 | 接受存储过程的处理结果 |
| inout | 输入/输出 | 既可以作为输入又可以作为输出 |
- 例子
```mysql
in -- 把数据传给存储过程处理
out -- 用来保存存储过程的执行结果
inout -- 既有in类型参数的功能又有out类型参数的功能
-- 语法格式
create procefure 库名.名称(参数类型 参数名 数据类型 ,……)
begin
调用定义的参数;
end
-- 注意: 在调用有参数的存储过程时,必须给存储过程传参,不然 属于语法错误
-- 例子
-- in 类型
user tarena;
delimiter //
create procedure tarena.p3(in dept_no int)
begin
select dept_id ,count(*) 总人数 from tarena.employees where dept_id = dept_no group by dept_id ;
end //
delimiter ;
call tarena.p3(3) ; -- 就是根据参数的变化,所处的部门就会跟随变化
delimiter //
create procedure tarena.p4(in dept_no int)
begin
select dept_name ,count(*) 总人数 from tarena.employees e inner join tarena.departments d on e.dept_id = d.dept_id where e.dept_id = dept_no group by e.dept_id ;
end //
delimiter ;
call tarena.p4(3) ;
-- out 的例子
select email from employees where name = '刘倩';
select email into @mail from employees where name = '刘倩';
select @mail
delimiter //
create procedure tarena.p5( in emp_name varchar(10) ,out mail varchar(25) )
begin
select email into mail from tarena.employees where name = emp_name;
end //
delimiter ;
insert into tarena.employees(name,email) values ('john','[email protected]'),('jerry','[email protected]');
call tarena.p5('john', @x); -- 调用创建过程使用并赋值函数
select @x
call tarena.p5('汤华', @x); -- 没有设置相应的字符集,所以会报错
-
show create database tarena \G -- 查看tarena的字符集
-- 例子
select name from tarena.employes ;
-- 想让存储过程处理中文数据,必须保证存储过程归属使用的字符集是中文字符集才行
show create database tarena\G
alter database tarena default character set utf8;
-- 每改之前创建的存储过程是无效的
drop procedure tarena.p5;
-- 在次创建上面的p5 的存储过程;
-- 再次测试
call tarena.p5('汤华', @x); -- 再此测试,就发现是可以使用中文的存储过程赋值了
-- inout例子(既有in和out的)
delimiter //
create procedure tarena.myadd(INOUT i int)
begin
set i = i+100;
end //
delimiter ;
call tarena.myadd(2)
select body from mysql.proc where name = 'myadd';
-- 输入输出参数时候时,必须要变量接
set @x = 100;
call tarena.myadd(@x);
select @x;
--
if语句 语法(自上向下遇到匹配就执行并结束if语句)
if 条件 then
语句;
end if ;
if 条件 then
语句1;
else
语句2;
end if;
if 条件 then
语句1;
elseif 条件2 then
语句2;
else
语句3;
end if;
- 例子
```mysql
--
delimiter //
create procedure tarena.deptype_pro
(IN no int ,OUT dept_type varchar(5))
begin
declare type varchar(5);
select dept_name into type from departments where dept_id = no;
if type = '运维部' then set dept_type = '技术部';
elseif type = '测试部' then set dept_type = '技术部';
elseif type = '开发部' then set dept_type = '技术部';
else set dept_type = '非技术部' ;
end if ;
end //
delimiter ;
call deptype_pro(1,@x);
select @x;
case 语句 语法(多条路径中选择一条路径执行)
case 变量|表达多| 字段
when 判断的值1 then 返回值1;
when 判断值2 then 返回值2;
。。。
else 返回值n;
end case;
什么是循环:要重复执行的命令 放在循环语句 ,循环多少次取决于循环语句的判断条件
存储过程支持的循环结构有:while 循环 loop循环 repeate 循环
while 、loop、repeat 语法如下
[标签:] while 循环条件 do //只有条件成立才执行循环,如果首次判断没满足直接推出循环
循环体;
end while[标签];
[标签:]loop /无条件的死循环 没有判断条件
循环体;
end loop [标签]
[标签:] repeat //至少循环1次,(先执行循环体,再判断条件 条件不成立时再次执行循环)
循环体;
untile 循环结束条件
end repeat [标签];
例子
-- while 循环例子
delimiter //
create procedure tarena.while_pro(in i int)
begin
declare j int default 1;
while j < i do insert into tarena.departments(dept_name) values ('hr');
set j = j + i;
end while ;
end //
delimiter ;
select * from tarena.departments ;
call tarena.while_pro(3);
select * from tarena.departments ;
-- loop循环例子
delimiter //
create procedure tarena.loop2()
begin
declare i int default 1 ;
loop select sleep(1),i;
end loop;
end //
delimiter ;
-- sleep() 睡眠1秒
call tarena.loop2();
show processlist; -- 相当于 ps aux
kill 相应的id ;
-- repeate 循环 例子
delimiter //
create procedure tarena.repeat_pro(in i int)
begin
declare j int default 1;
repeat
set j = j + 1 ;
insert into tarena.departments(dept_name) values ('sales');
until j > i
end repeat ;
end //
delimiter ;
select * from departments ;
call tarena.repeat_pro(3);
select * from departments ;
控制循环的执行
默认只有符合循环的判断条件,都会重复执行循环体
我们可以通过循环结构控制语句,在不改变循环判断条件的情况下 跳过某次循环
例子
-- 例子
delimiter //
create procedure tarena.p11()
begin p:loop leave p;
select sleep(1);
select 'one';
end loop p ;
end //
delimiter ;
call tarena.p11(); -- 会发现什么也没有输出
delimiter //
create procedure tarena.p12()
begin
declare i int default 1;
set i = 1 ;
loop
select i= i + 1 结果 ;
select sleep(1);
end loop;
end //
delimiter ;
call p12;
-- iterate
delimiter //
create procedure tarena.while_pro3( in i int)
begin
declare j int default 0;
a:while j < i do set j = j+ 1;
if mod(j,2)=0 then iterate a;
end if;
insert into tarena.departments(dept_name) values (concat('hr',j));
end while a;
end //
delimiter ;
call tarena.while_pro3(20);
select * from departments ;
什么是数据备份
为什么要做备份
什么是恢复
怎么恢复
数据备份方式:
根据备份方法分为:物理备份 逻辑备份
备份操作
恢复操作
实例
[root@mysql1 ~]# mkdir /bakdir
[root@mysql1 ~]# systemctl stop mysqld.service
[root@mysql1 ~]# cp -r /var/lib/mysql /bakdir/
[root@mysql1 ~]# ls /bakdir/
[root@mysql1 ~]# systemctl start mysqld
[root@mysql1 ~]# tar zcf /bakdir/mysql.tar.gz /var/lib/mysql
[root@mysql1 ~]# ls /bakdir/
[root@mysql1 ~]# rm -rf /var/lib/mysql
# 有些数据库会发现数据库没有了,会做数据库初始化
[root@mysql1 ~]# rm -rf /var/lib/mysql
[root@mysql1 ~]# systemctl stop mysqld.service
[root@mysql1 ~]# killall -9 mysqld
[root@mysql1 ~]# cp -r /bakdir/mysql /var/lib/mysql
[root@mysql1 ~]# chown -R mysql:mysql /var/lib/mysql
[root@mysql1 ~]# ll -d /var/lib/mysql
[root@mysql1 ~]# systemctl start mysqld
[root@mysql1 ~]# mysql -uroot -p123456
完全备份
完全恢复
注意:恢复库时库名可以省略
注意:备份和恢复数据库服务必须是运行状态
库名表示方式
库名 表名列表 //备份1张表或多张表
-B 库名列表 //备份1个库或多个库
-all-databases 或 -A //备份1台服务器所有数据
注意:恢复数据时,会删除目标服务器同名的库表 再恢复数据
# mysqldump是mysql安装后提供的命令
mysqldump -uroot -p123456 tarena user > /bakdir/user.sql -- 一个表
ls /bakdir/
mysqldump -uroot -p123456 -B tarena > /bakdir/tarena.sql -- 一个库
mysqldump -uroot -p123456 tarena employees salary > /bakdir/emplotees_salary.sql -- 多个表
mysqldump -uroot -p123456 -B tarena studb > /bakdir/tarena_studb.sql -- 多个库
mysqldump -uroot -p123456 -A > /bakdir/all.sql -- 一个服务器
# 使用恢复
drop database tarena;
[root@mysql1 ~]# mysql -uroot -p123456 < /bakdir/tarena.sql
show databases;
use tarena ;
show tables ;
# 51 恢复备份
[root@mysql1 ~]# scp -r /bakdir/ 192.168.4.51:/
[root@mysql2 ~]# mysql -uroot -pNSD2110...a < /bakdir/tarena_studb.sql
[root@mysql2 ~]# mysql -uroot -pNSD2110...a
mysql> show databases;
# 51 删除表跟恢复表
mysql> use tarena
mysql> drop table user ;
[root@mysql2 ~]# mysql -uroot -pNSD2110...a tarena < /bakdir/user.sql
[root@mysql2 ~]# mysql -uroot -pNSD2110...a
mysql> use tarena
mysql> show tables ;
use tarena;
select count(*) from tarena.user
insert into tarena.user(name,id) values ('a',211); -- 插入数据
delete from tarena.user ;
select * from tarena.user ;
source /bakdir/user.sql -- 恢复数据
select count(*) from tarena.user ; -- 恢复的数据会发现直线插入的数据是没有的
适合备份数据量少的数据
说明 启用mysql的binlog日志文件 实现对数据的实时备份
配置项 | 用途 |
---|---|
server_id=数字 | 指定id值(1-255) |
log_bin | 启用binlog日志 |
max_binlog_size=数值m | 指定日志文件容量,默认1G |
binlog相关文件
show master status ; -- 说明是空的,没有binlog日志
vim /etc/my.cnf
log_bin -- 删除#
server_id = 50 -- 手动添加
[root@mysql1 ~]# systemctl restart mysqld
mysql> show master status ; -- 编号为1 到达1G 的容量 会自动创建编号为2 的文件
-- 这个文价存放在
ls /var/lib/mysql/mysql1-bin.000001
/var/lib/mysql/mysql1-bin.index
mysqlbinlog bin.000001 -- 命令行查看binlog内容
修改日志文件存放的目录和名称
[root@mysql1 ~]# vim /etc/my.cnf
log_bin=/mylog/plj -- 删除#
server_id = 50 -- 手动添加
[root@mysql1 ~]# mkdir /mylog
[root@mysql1 ~]# chown mysql /mylog/
[root@mysql1 ~]# setenforce 0
[root@mysql1 ~]# systemctl restart mysqld
[root@mysql1 ~]# ls /mylog/ -- 发现下面会有文件
mysql> show master status; -- 发现file名字会有发生更改
-- 每个文件的编号都是从1开始的
创建新日志文件
systemctl restart mysql -- 重启服务
mysqldump -u用户名 -p密码 -flush-logs -- 加-flush-logs 选项
flush logs ; -- mysql刷新日志命令
show master status ; -- 查看正在使用的日志
show binary logs ; -- 查看已有的日志文件
purge master logs to'日志名' -- 删除编号之前的日志
reset master ; -- 删除所有日志,重新创建日志
show binlog events in '日志文件名' -- 查看日志文件内容
例子
-- 手动创建新的日志文件 正常情况下,只有大于1G才会创建新的日志文件
mysql> flush logs; -- 生成新的日志文件
mysql> show master status ;
[root@mysql1 ~]# systemctl restart mysqld -- 重启就会无条件创新新的日志文件
mysql> show master status ;
mysqldump -uroot -p123456 --flush-logs -B tarena > /opt/tarena.sql -- 也会创建新的日志文件
mysql -uroot -p123456 -e'show master status';
-- 删除已有的日志文件
reset master; -- 删除所有日志,重新创建日志
purge master logs to'日志名' -- 删除编号之前的日志
-- 插入数据,直接访问日志内容
insert into tarena.user(name,uid) values('ss',123);
show binlog events in 'plj.000001';
把查看到的文件内容管道给连接mysql服务的命令执行
查看文件全部内容,适用于恢复所有数据
– 适用于日志没有记录delete from命令
mysqlbinlog /目录/文件名 | mysql -uroot -p密码
查看文件制定范围内容,使用恢复部分数据
mysqlbinlog 选项 /目录/文件名 |mysql -uroot -p密码
选项说明
选项 | 用途 |
---|---|
-start-datetime=‘yyyy-mm-dd hh:mm:ss’ | 起始时间 |
-stop-datetime=‘yyyy-mm-dd hh:mm:ss’ | 结束时间 |
-start-postion=数字 | 起始偏移量 |
-stop-postion=数字 | 结束偏移量 |
例子
-- 在50 完成实验
-- 对tarena库做完全备份
mysql -uroot -p123456 -e 'select count(*) from tarena.user '
mysql -uroot -p123456 -e 'show master status;'
mysqldump -uroot -p123456 --flush-logs tarena user > /bakdir/user1.sql
mysql -uroot -p123456 -e 'show master status ' -- 发现出现了新的日志文件
mysql -uroot -p123456 -e "insert into tarena.user(name) values('sss')"-- 同样操作,3行
mysql -uroot -p123456 -e 'show master status '
mysql -uroot -p123456 -e 'select count(*) from tarena.user '
-- 在51数据库tarena库下的user记录删除,使用50 的备份文件加binlog日志恢复日志文件
mysql -uroot -pNSD2110...a -e'delete from tarena.user'
mysql -uroot -pNSD2110...a -e'select count(*) from tarena.user '
scp /bakdir/user1.sql 192.168.4.51:/opt/
scp /mylog/plj.000002 192.168.4.51:/opt/
mysql -uroot -pNSD2110...a tarena < /opt/user1.sql
mysql -uroot -pNSD2110...a -e'select count(*) from tarena.user '
mysqlbinlog /opt/plj.000002 | mysql -uroot -pNSD2110...a
mysql -uroot -pNSD2110...a -e'select count(*) from tarena.user '
-- 使用binlog日志回复指定的数据
-- 适用于日志文件里面交替出现插入 insert更新update 删除delete 的命令
mysqldump 选项 /目录/日志文件名 | mysql -uroot -p密码
-- 通过选项控制读取日志文件记录命令的范围
-- 可以通过时间范围选项 只读取指定时间范围内记录sql命令
-- 也可以通过偏移量范围选项 只读取制定偏移量范围内记录的sql命令
!!说明 要执行命令所在 范围要自己查看 日志的内容 获得
例如
mysqlbinlog --start-position=9088 --stop-position=10923 /mylog/plj.000002 | mysql -uroot -p123456
-- 接着上个实验做
mysql -uroot -p123456 -e 'show master status'
mysql -uroot -p123456 -e 'select count(*) from tarena.user '
mysql -uroot -p123456 -e "insert into tarena.user(name) values ('jj')"
mysql -uroot -p123456 -e "insert into tarena.user(name) values ('ajj')"
mysql -uroot -p123456 -e "insert into tarena.user(name) values ('bjj')"
mysql -uroot -p123456 -e "delete from tarena.user"
mysql -uroot -p123456 -e "insert into tarena.user(name) values ('cjj')"
scp /mylog/plj.000002 192.168.4.51:/opt/
mysqlbinlog /opt/plj.000002 | mysql -uroot -pNSD2110...a -- 直接恢复就会报错(主键的错误) 但是会把删除的命令执行一遍
-- 就是说明表里有交替的记录 不适用从到读到尾巴
mysql -uroot -p123456 -e 'show master status'
mysql -uroot -p123456 -e “show binlog events in 'plj.000002'”
-- 直接查看的话没法断定那条记录跟那条记录
-- 指定范围,要先修改日志文件的格式
查看日志当前记录格式
修改日志记录格式
vim /etc/my.cof
[mysql]
binlog_format='名称'
systemctl restart mysqld
实例
mysql -uroot -p123456 "show variables like '%binlog%'"
binlog_format -- 查处这个变量名 默认格式就是row 就是行模式 ,修改为混合模式
vim /etc/my.cnf
[mysqld]
binlog_format='mixed' -- 修改这一项
systemctl restart mysqld
-- 重启之后日志就会自动更新,然后查看的日志就是plj.000003最新的这个
mysql -uroot -p123456 -e "show master status "
mysql -uroot -p123456 -e "show binlog events in 'plj.000004'"
mysql -uroot -p123456 -e "delete from tarena.user"
mysql -uroot -p123456 -e " show binlog events in 'plj.000004'"
-- 再次查看就会看到正条sql命令
mysql -uroot -p123456 -e " insert into tarena.user(name) values('A')"
mysql -uroot -p123456 -e " insert into tarena.user(name) values('B')"
mysql -uroot -p123456 -e " insert into tarena.user(name) values('C')"
mysql -uroot -p123456 -e " update tarena.user set name = 'abc' where name = 'B'"
mysql -uroot -p123456 -e " insert into tarena.user(name) values('XY')"
mysql -uroot -p123456 -e " show binlog events in 'plj.000004'"
mysql -uroot -p123456 -e "select count(*) from tarena.user"
-- 就可以查看到范围了
-- 在51里面操作
scp /mylog/plj.000004 192.168.4.51:/opt/
-- 在51是直接看不了plj.000003的,只能在50里面查要执行命令的范围,然后在51主机执行日志范围命令记录内的数据
mysql -uroot -p123456 -e " show binlog events in 'plj.000004'" -- 50主机
mysql -uroot -pNSD2110...a -e 'select count(*) from tarena.user '
mysqlbinlog --start-position=1558 --stop-position=2338 /opt/plj.000004 | mysql -uroot -pNSD2110...a
mysql -uroot -pNSD2110...a -e 'select count(*) from tarena.user '
-- 在50主机使用自己的binlog日志文件恢复数据
使用mysql -uroot -p123456 -e " show binlog events in 'plj.000004'"是查不到时间的,只能查到起始偏移量
mysql -uroot -p123456 -e "select count(*) from tarena.user"
mysqlbinlog /mylog/plj.000004 -- 可以看到相应的时间, 命令的上方的#就是起始时间 结束时间的话必须要包含commit的时间
mysql -uroot -p123456 -e "delete from tarena.user"
mysql -uroot -p123456 -e "select count(*) from tarena.user"
mysqlbinlog --start-datetime="2022-02-17 16:49:20" --stop-datetime="2022-02-17 16:49:29" /mylog/plj.000004 | mysql -uroot -p123456
mysql -uroot -p123456 -e "select count(*) from tarena.user"
优点:在线热备不锁表 适合生产环境下的备份要求
一款强大的在线热备份工具
scp percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm libev-4.15-1.el6.rf.x86_64.rpm 192.168.4.50:/root
yum -y install percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm libev-4.15-1.el6.rf.x86_64.rpm
-- 完全备份与恢复
innobackupex -uroot -p密码 /备份文件存放的目录 [--no-timestamp] 目录不需要事先创建,目录一次只能存放一次目录
-- 恢复数据的命令格式
[root@mysql1 ~]# ls /fullbak
[root@mysql1 ~]# innobackupex -uroot -p123456 /fullbak
[root@mysql1 ~]# ls /fullbak -- 发现存放了以系统时间为名的文件夹
[root@mysql1 ~]# rm -rf /fullbak/
[root@mysql1 ~]# innobackupex -uroot -p123456 /fullbak --no-timestamp
[root@mysql1 ~]# ls /fullbak -- 蓝色的是库 黑色是记录备份记录的备份信息
[root@mysql1 ~]# cat /fullbak/xtrabackup_checkpoints -- 备份信息
backup_type = full-backuped # 说明了是完全备份数据
from_lsn = 0
to_lsn = 8794342
last_lsn = 8794351
compact = 0
recover_binlog_info = 0
-- 备份的过程中不锁表,也就是说在备份的时候允许客户进行读写的操作
要求数据库清空
具体如下
rm -rf /var/lib/mysql/*
cat /fullbak/xtrabackup_checkpoints
innobackupex --copy-back /fullbak/
chown -R mysql:mysql /var/lib/mysql/
systemctl start mysqld
ll -d /var/lib/mysql/
ll /var/lib/mysql/
systemctl start mysqld
具体如下:
相关命令
alter table 库名.表名 discard tablespace # 删除表空间
innobackupex --apply-log --export 数据完全备份目录 # 导出表信息
cp /备份目录/库名/表名/{ibd,cfd,exp} /var/lib/mysql/库名 # 拷贝表信息文件
chown -R mysql:mysql /var/lib/mysql/库名 # 修改所有者/组
alter table 库名.表名 import tablespace # 导入表空间
rm -rf /var/lib/mysql/库名/表名.{cfd,exp} # 删除表信息文件
select * from 库名.表名 ; # 查看表记录
例子
mysql -uroot -p123456 -e 'select * from tarena.user '
mysql -uroot -p123456 -e 'alter table tarena.user discard tablespace;'
ls /var/lib/mysql/tarena/user.*
ls /fullbak//tarena/user.*
innobackupex --apply-log --export /fullbak/
ls /fullbak//tarena/user.*
ls /var/lib/mysql/ib_logfile*
cp /fullbak/tarena/user.ibd /var/lib/mysql/tarena/
cp /fullbak/tarena/user.cfg /var/lib/mysql/tarena/
cp /fullbak/tarena/user.exp /var/lib/mysql/tarena/
ll /var/lib/mysql/tarena/
chown -R mysql:mysql /var/lib/mysql/tarena/
ll /var/lib/mysql/tarena/
mysql -uroot -p123456 -e 'alter table tarena.user import tablespace'
mysql -uroot -p123456 -e 'select * from tarena.user '
rm -rf /var/lib/mysql/tarena/user.cfg
rm -rf /var/lib/mysql/tarena/user.exp
增量备份
innobackupex -u用户名 -p密码 -incremental /增量备份存放的目录名 --incremental-basedri=/上次备份文件存放的目录名 [--no-timestamp:不使用时间戳格式的创建目录存放数据]
增量恢复
innobackupex --apply-log -redo-only /首次备份目录名 #准备恢复数据
innobackupex --apply-log -redo-only /首次备份目录名 --incremental-dir=/目录名 # 合并数据
innobackupex --copy-back /目录名 # 拷贝数据
准备恢复数据(声明合并的起始位置)
合并数据(把增量数据合并)(合并数据的顺序要与备份的顺序一致)
拷贝数据
常用选项 | 含义 |
---|---|
–apply-log | 准备恢复数据 |
–redo-only | 日志合并 |
–incremental /目录名 | 新数据存放目录 |
–incremental-basedir=/目录名 | 备份新数据参考目录 |
–incremental-dir=/目录名 | 合并数据存放目录 |
例子
innobackupex -uroot -p123456 /allbak --no-timestamp
ls /allbak/
mysql -uroot -p123456 -e "insert into tarena.user(name,uid) values('sda',31231)"
mysql -uroot -p123456 -e "select count(*) from tarena.user"
innobackupex -uroot -p123456 --incremental /newldri --incremental-basedir=/allbak/ --no-timestamp
ls /newldri/
# 判断数据是
[root@mysql1 ~]# cat /allbak/xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0 # 完全被分是从0 开始备份的
to_lsn = 7924691 # 这是结束的序列号
last_lsn = 7924700
compact = 0
recover_binlog_info = 0
[root@mysql1 ~]# cat /newldri/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 7924691 # 因为是增量备份,所以是接着上次备份结束的序列号开始
to_lsn = 7929110# 这是结束的序列号
last_lsn = 7929119
compact = 0
recover_binlog_info = 0
ls /var/lib/mysql/ib_logfile*
# 就是参看下面的日志文件的lsn 的序列号是否相同,如果参考的数据不一致的话,说明了数据是有过变化的,有变化的话,就参看上次备份的序列号,接着上次备份的数据的序列号,备份到最新的数据的序列号
# 增量恢复例子
innobackupex --apply-log -redo-only /首次备份目录名
innobackupex --apply-log -redo-only /首次备份目录名 --incremental-dir=/目录名
innobackupex --copy-back
scp -r /allbak 192.168.4.51:/root/
scp -r /newldri/ 192.168.4.51:/root/
scp -r /newldir1/ 192.168.4.51:/root/
scp -r libev-4.15-1.el6.rf.x86_64.rpm percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm 192.168.4.51:/root/
# 51主机使用备份文件恢复数据
systemctl stop mysqld.service
rm -rf /var/lib/mysql/*
yum -y install libev-4.15-1.el6.rf.x86_64.rpm percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm
# 指定首次备份的目录
innobackupex --apply-log --redo-only /root/allbak/
cat allbak/xtrabackup_checkpoints
# 合并数据
innobackupex --apply-log --redo-only /root/allbak/ --incremental-dir= /root/newldri/
innobackupex --apply-log --redo-only /root/allbak/ --incremental-dir=/root/newldri/
cat allbak/xtrabackup_checkpoints
cat newldri/xtrabackup_checkpoints
innobackupex --apply-log --redo-only /root/allbak/ --incremental-dir=/root/newldir1/
cat allbak/xtrabackup_checkpoints
cat newldri/xtrabackup_checkpoints
cat newldir1/xtrabackup_checkpoints
rm -rf newldri/ newldir1/ # 因为已经把数据都合并了/root/allbak/ ,所以这两个文件没什么用了,但是还是有数据的
# 数据回复
innobackupex --copy-back /root/allbak/ # 将数据拷贝回复到数据库目录下
ls /var/lib/mysql
ll /var/lib/mysql
chown -R mysql:mysql /var/lib/mysql
ll /var/lib/mysql
# 重启服务
systemctl start mysqld
mysql -uroot -p123456 -e 'select count(*) from tarena.user '
具体操作
是实现数据自动备份的存储结构 分为两种角色
主数据库服务器master : 被网站连接的数据库服务器
从数据库服务器slave : 同步主数据库服务器上数据的 数据库服务器
master角色的数据库服务器 必须启用binlog日志
slave角色的数据库服务器有IO线程和sql线程
IO线程: 负责拷贝master服务器binlog日志里的sql命令 到本机 并把名存放到本机的中继日志文件里
sql线程: 负责执行本机中继日志文件里保存的sql命令 把数据存放到本机的表里
主服务器需要做的配置
从服务器需要做的配置
制定server_id并重启数据库服务器
要确保与主数据库服务器数据一致(只能大于或等于主服务器,不能小于主服务器)(如果是2台崭新的数据库服务器 数据默认是一样的)
管理员登录指定主服务器信息
启动slave进程 (mysql内置的进程)
查看进程状态信息
IO线程 :yes
SQL线程 : yes
配置51
# 开启binlog日志
vim /etc/my.cnf
log_bin=master51
server_id=51
systemctl restart mysqld
mysql -uroot -p123456
grant replication slave on *.* to repluser@"%" identified by "123456";
# 如果密码没有改过策略的话,还是原来那种复杂的密码 类似于123qqq...a
show master status;
配置52
vim /etc/my.cnf
[mysqld]
server_id=52
systemctl restart mysqld
mysql -uroot -p123456
show slave status \G # 没有配置之前不是从服务器
change master to master_host='192.168.4.51', master_user='repluser',master_password='123456',master_log_file='master51.000001',master_log_pos=441;
show slave status \G # 已经发现有数据了
Slave_IO_Running: No IO没有启动
Slave_SQL_Running: No SQL没有启动
start slave;
show slave status \G
# 如果启动了了没有发现是两个都是yes,那么先
stop slave;
change master to master_host='192.168.4.51',master_user='repluser',master_password='123456',master_log_file='master51.000001',master_log_pos=441;
#由于是直接复制配置文件跟数据库过去的,所以需要在vim /var/lib/mysql/auto.cnf 里面的内容换以一个字母或数字就行,然后再重启,再进去重启slave
查看报错信息 show slave status \G
Last_IO_Error:
Last_SQL_Error:
Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work # 说明了 UUIDs相同 所以需要在vim /var/lib/mysql/auto.cnf 里面的内容换以一个字母或数字就行,然后再重启,再进去重启slave
测试配置:
在主数据库服务器51本机管理员登录创新库表
添加51上面添加数据
[root@mysal51 ~]# mysql -uroot -p123456 -e 'create database db1'
[root@mysal51 ~]# mysql -uroot -p123456 -e 'create table db1.a(id int)'
mysql -uroot -p123456 -e 'grant all on db1.* to yaya@"%" identified by "123qqq...A"'
在50上面登录51数据库服务器以yaya身份
[root@mysql51 ~]# mysql -h192.168.4.51 -uyaya -p123qqq...A
use db1;
insert into a values(123);
在52上面就可以查看所有的数据了
接下来就是一主多从的结构
vim /etc/my.cnf
[mysqld]
server_id=52
systemctl restart mysqld
# 51对数据做完全备份 把备份文件拷贝给从服务器
[root@mysal51 ~]# mysqldump -uroot -p123456 -B mysql db1 > /root/two.sql
[root@mysal51 ~]# scp two.sql 192.168.4.53:/root
# 53数据恢复
mysql -uroot -p123456 < two.sql
mysql -uroot -p123456
show slave status \G # 没有配置之前不是从服务器
change master to master_host='192.168.4.51', master_user='repluser',master_password='123456',master_log_file='master51.000001',master_log_pos=1295; # 注意日志文件名需要事先查看文件名和偏移量
start slave ;
show slave status \G
测试
在50里面使用yaya用户添加数据,然后在53数据库服务器查看数据
将53 还原为独立的数据库服务器
[root@mysql53 ~]# cd /var/lib/mysql
[root@mysql53 mysql]# cat master.info
[root@mysql53 mysql]# rm -rf master.info
[root@mysql53 mysql]# ls mysql53-relay-bin.
[root@mysql53 mysql]# ls mysql53-relay-bin.
[root@mysql53 mysql]# ls *-relay-bin*
[root@mysql53 mysql]# cat mysql53-relay-bin.index
[root@mysql53 mysql]# rm -rf *-relay-bin*
[root@mysql53 mysql]# ls relay-log.info
[root@mysql53 mysql]# cat relay-log.info
[root@mysql53 mysql]# rm -rf relay-log.info
[root@mysql53 mysql]# systemctl restart mysqld
[root@mysql53 mysql]# mysql -uroot -p123456
mysql> show slave status \G
mysql> drop database db1;
准备54 和 55 数据库服务器
第一步:配置主服务器53
启用binlog日志文件
用户授权
查看日志信息
第二步:配置技术主服务器又是从服务器的54
注意:从服务器自己也有服务器的时候,要启用级联复制功能
第三步:配置从服务器55
制定server_id并重启数据服务
管理员的登录制定
# 53
[root@mysql53 mysql]# vim /etc/my.cnf
binlog=master
server_id=53
[root@mysql53 mysql]# systemctl restart mysqld
[root@mysql53 mysql]# mysql -uroot -p123456
grant replication slave on *.* to repluser@"%" identified by '123456';
show master status ;
# 54
vim /etc/my.cnf
[mysqld]
server_id=54
validate_password_policy=0
validate_password_length=6
log_bin=master54
log_slave_updates
mysql -uroot -p123456
grant replication slave on *.* to repluser@'%' identified by '123456';
change master to master_host='192.168.4.53' ,master_user='repluser' , master_password='123456',master_log_file='master53.000001',master_log_pos=441;
start slave ;
show slave status;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
show master status ;
# 55
vim /etc/my.cnf
server_id=55
change master to master_host='192.168.4.54' ,master_user='repluser' , master_password='123456',master_log_file='master54.000002',master_log_pos=441;
start slave ;
show slave status \G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
# 在主服务器53添加用户
# 客户端使用添加的用户连接主服务器 建库建表 存储数据
# 客户端分别连接服务器54和55 可以查看到同样的数据
# 53
mysql -uroot -p123456
grant all on webdb.* to yaya6688@'%' identified by '123456';
# 50
mysql -h192.168.4.53 -uyaya6688 -p123456
create database webdb;
show databases;
create table webdb.t1(id int);
insert into webdb.t1 values(101);
select * from webdb.t1;
# 54和55 查看创建的记录
show databases;
select * from webdb.t1;
主主结构准备数据库服务器56和57
# 主主同步结构:2太数据库服务器互为主从
# 具体配置步骤如下
第一步 配置服务器56
# 启用binlog 日志
# 用户授权
# 查看日志信息
第二步 配置数据库服务器57
# 启用binlog日志
# 用户授权
# 指定主服务器侵袭
查看binlog信息
第三步 配置数据库服务器56
#指定主服务器信息
# 56
vim /etc/my.cnf
server_id=56
binlog-master56
systemc retstart mysqld
mysql -uroot -p123456
grant replication slave on *.* to repluser@'%' identified by '123456';
show master status ;
# 57
server_id=57
log_bin=master57
systemctl restart mysqld
mysql -uroot -p123456
grant replication slave on *.* to repluser@'%' identified by '123456';
change master to master_host='192.168.4.56' ,master_user='repluser' , master_password='123456',master_log_file='master56.000001',master_log_pos=441;
start slave ;
show slave status \G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
show master status ;
# 56 配置57 的从服务器
change master to master_host='192.168.4.57' ,master_user='repluser' , master_password='123456',master_log_file='master57.000001',master_log_pos=441;
start slave ;
show slave status \G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
# 测试配置
# 具体操作如下
# 在任意一台数据库服务器添加用户都可以
# 客户端使用添加用户连接 任意数据库存储数据都可以
# 客户端连接任意一台查看数据
# 56
grant all on db2.* to haha@'%' identified by '123456';
# 57
create database db2;
create table db2.t1(id int );
insert into db2.t1 values(199);
# 56
select * from db2.t1;
insert into db2.t1 values (100);
# 57
select * from db2.t1;
主从同步数据复制模式(实验在50主机完成
讲的是:从数据库服务器与主数据库服务器 做数据同步时的工作方式
分为2中工作方式
异步复制模式:(默认)
半同步复制模式:
思考:两种模式的优缺点?
# 在50数据库服务器启用半同步复制功能
# 具体操作如下
# 第一步:安装功能模块并查看 安装状态
# 安装master模块
# 安装slave模块
# 第二步:启用功能模块查看状态
# 启用master模块
# 启用slave模块
# 查看启用状态
# 第三步:永久配置(命令配置数据库服务后会还原)
# 第四步
验证永久配置
重启数据库服务,查看模块的状态依然还是启动状态
# 50
mysql -uroot -p123456
install plugin rpl_semi_sync_master soname "semisync_master.so"; # master模块
install plugin rpl_semi_sync_slave soname "semisync_slave.so"; # slave模块
select plugin_name ,plugin_status from information_schema.plugins where plugin_name like "%semi%";
第二步
set global rpl_semi_sync_master_enabled=1;
set global rpl_semi_sync_slave_enabled=1;
show variables like "rpl_semi_%_enabled";
第三步在配置文件中编辑
vim /etc/my/cnf
# 安装模块
plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so;"
rpl_semi_sync_master_enabled=1
rpl_semi_sync_slave_enabled=1
第四步
systemctl restart mysqld
mysql -uroot -p123456
show variables like "rpl_semi_%_enabled";
主服务必须配置步骤
启用binlog日志文件 用户授权 查看日志信息
从服务器的必须配置步骤
制定server_id 并重启数据库服务
确保与主服务器数据一致:在主服务器做
50 做客户端
51、52 mysql一主一从结构
56 做读写分离服务器
图扑结构
客户端(网站) --》 读写分离服务器–》如果是查询的话直接发给slave服务器;如果是更改数据的话,直接发送发哦master服务器
实现数据读写分离功能的服务软件(mysql中间件)
中间件:指的就是架设在数据库服务和客户端之间的服务软件
中间件软件的功能各不相同,有实现分布式存储的 读写分离的
实现数据读写分离的开源服务前软件有:mysql-proxy maxscale MyCat
# 配置数据读写分离存储架构,具体操作如下
# 第一步:准备数据库服务器
# 配置mysql主从同步结构
# 把数据库服务器51配置master服务器
# 把数据库服务器52配置slave服务器
# 配置过程见上面的主从配置
# 查看52 从数据库服务器上面的IO和SQL线程是否为yes
show slave status \G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
# 在主机56配置读写发额不您里服务
# 说明56主机不他哦共数据存储服务器mysql
# 不需要运行mysqld
具体操作如下
1.安装软件
2.修改主配置文件
3.配置数据库服务前器
4.启动读写分离服务
5.查看监视信息
6.测试配置
yum -y install maxscale-2.1.2-1.rhel.7.x86_64.rpm
cp /etc/maxscale.cnf /root/ # 主配置文件的备份
vim /etc/maxscale.cnf
[maxscale] # 就是读写分离启动后的线程个数
threads=auto# threads=auto 设置为自动的个数,根据cpu的性能和个数去创建
[server1]
type=server
address=192.168.4.51
port=3306
protocol=MySQLBackend
[server2]
type=server
address=192.168.4.52
port=3306
protocol=MySQLBackend
[MySQL Monitor]
type=monitor
module=mysqlmon
servers=server1,server2
user=mysqla# 这里是监视server1和server2的用户
passwd=123456#这里是监视server1和server2的密码
monitor_interval=10000
[Read-Write Service]# 检查server1和2里面创建的用户
type=service
router=readwritesplit
servers=server1,server2
user=mysqlb # 检查mysql里面的用户
passwd=123456
max_slave_connections=100%
[MaxAdmin Service]
type=service
router=cli
[Read-Write Listener]
type=listener
service=Read-Write Service
protocol=MySQLClient
port=4006
[MaxAdmin Listener]
type=listener
service=MaxAdmin Service
protocol=maxscaled
socket=default
port=4016
# 51 和 52 数据库添加用户mysqla和mysqlb
# 因为两台数据库是主从同步结构,所以只需要在51上面添加的就可以,52会自动同步
# 51
grant replication slave ,replication client on *.* to mysqla@"%" identified by '123456';
replication slave 获取主从角色状态的权限
replication client 获取数据库服务状态的权限
grant select on mysql.* to mysqlb@"%" identified by '123456';
# 52
select user from mysql.user where user in ('mysqla','mysqlb');
# 启动56主机的读写分离服务
# 说明: 如果第二步和第三步配置有问题,及时启动了服务也不能正常工作
# 测试授权用户mysqla 和 mysqlb
mysql -h192.168.4.51 -ymysqla -p123456
mysql -h192.168.4.52 -umysqlb -p123456
# 启动读写分离服务
无论服务启动成功与否,都是会有日志文件 /var/log/maxscale/
maxscale /etc/maxscale.cnf
怎么查看服务有没有起来:直接查看端口4406
ss -tunlp | grep 4006
ss -tunlp | grep 4016
读写分离服务为期必须指定51和52 上数据库服务是否是运行
那台数据库是master角色服务器 那台是slae角色服务器
才能
maxadmin -uadmin -pmariadb -P4016
P(大写): 是指定端口号
p(小写):指定的是密码
MaxScale> list servers # 直接查看里面的状态master和slave
# 杀死进程
killall -a maxscale
# 总结一下
# 测试配置
具体操作如下
第一步:在主服务器上面51 添加用户 (给客户端连接服务使用)
第二步: 给客户端联机分离服务器,查询数据和存储数据
第三步: 测试数据读写分离
# 51
create database bbsdb;
create table bbsdb.a(id int);
grant select ,insert on bbsdb.* to jing99@'%' identified by '123456';
# 在客户端访问51
mysql -h192.168.4.56 -P4006 -ujing99 -p123456 # 这里提示一下就是mysqlb是检查上面的用户和对应的访问权限
insert into bbsdb.a values(666);
select * from bbsdb.a;
# 检测
select @@hostname; 显示主机名
mysql -h192.168.4.56 -P4006 -ujing99 -p123456
select @@hostname; 显示的是52的主机名
insert into bbsdb.a values (999); # 如果这过数据没有在51上面添加的话,在52上面查的话,是不会查的到数据的,
select * from bbsdb.a;
# 所以验证了,查的就是在52上面查的,插入数据的就是在51上面操作的
测试读写分离的第二种方法
第一步 在从服务器添加新数据(在从服务器添加主服务器不会同步)
第二步 客户端连接写分离服务器连接查询
# 52
insert into bbsdb.a values (252);
# 51
select * from bbsdb.a; # 发现上面是没有252 的
# 56
select * from bbsdb.a; # 发现上面是有252的,所以说明了查询是在52上面查询的,而不时是在51上面查询的。
在56主机mysql多实例的配置
说明 要把5.7 版本的mysql服务停止
rpm -qa |grep mysqld
systemctl stop mysqld
systemctl disable mysqld
rm -rf /etc/my.cnf
scp -r /linux-soft/4/mysql/mysql-5.7.20-linux-glibc2.12-x86_64.tar.gz 192.168.4.56:/root
tar xf mysql-5.7.20-linux-glibc2.12-x86_64.tar.gz
mv mysql-5.7.20-linux-glibc2.12-x86_64 /usr/local/mysql
# 部署服务运行环境
id mysql || useradd mysql
rpm -q libaio || yum -y install libaio
# 把命令添加到系统环境变量$PATH
ls /usr/local/mysql/bin/ # 源码路径
vim /etc/bashrc
export PATH=/usr/local/mysql/bin:$PATH
echo $PATH
source /etc/bashrc # 执行环境变量 ,将/usr/local/mysql/bin/添加到path里面
echo $PATH
编写多实例服务的配置文件(要求在56主机运行2个数据库服务)
说明:在一台物理主机上运行多个数据库服务器,每个服务都要有如下的独立文件
vim /etc/my.cnf
socket=/var/lib/mysql/mysql.sock 这一行是自带的:
ls /var/lib/mysql # 就是如果服务停止了就,没有这个文件了,没有这个文件,就会连接失败
# 就是如果在一台服务器跑多个数据库的时候必须要有多个socker文件啦
独立文件:
管理多实例服务的运行参数
[mysqld_mulit] 指定管理多实例 服务的运行参数
修改数据库管理员密码使用的命令
user=root 去启动多实例服务的用户名
mysqld=/usr/local/mysql/bin/mysqld_safe 多实例服务启动是调用的启动文件
mysqladmin= /usr/local/mysql/bin/mysqladmin
[mysqld数字]
datadir=数据库目录
port=端口号
pid-file=存放进程pid号文件
log-error=存放服务启动信息和报错信息的日志文件
如果上面有/etc/my.cnf的话需要删除
启动实例
在56主机运行2个数据库服务
ls /etc/my.cnf # 没有,因为上面已经删除了
vim /etc/my.cnf
[mysqld_multi]
user=root
mysqld=/usr/local/mysql/bin/mysqld_safe
mysqladmin= /usr/local/mysql/bin/mysqladmin
[mysqld1]
datadir=/dir1
port=3307
log-error=/dir1/mysqld1.err
pid-file=/dir1/mysqld2.pid
socket=/dir1/mysqld1.sock
[mysqld2]
datadir=/dir2
port=3308
log-error=/dir2/mysqld2.err
pid-file=/dir2/mysqld2.pid
socket=/dir2/mysqld2.sock
# 启动实例1
mysqld_multi start 1 # 会创建数据库目录的,最后一行会出现密码
ss -tunlp | grep 3307
ls /dir1/
mysql -uroot -p'VTq(X+S -S /dir1/mysqld1.sock # 初始密码
set password='123456'; # 没有密码策略要求
mysql -uroot -p123456 -S /dir1/mysqld1.sock
# 停止服务,需要跟上用户名和密码
mysqld_multi stop --user=root --password=123456 2 # 停止实例2
ls /dir2/ # 发现没有/dir2/mysqld2.sock 文件了
ss -tumlp | grep 3308 # 端口号也没有了
使用mysql服务存储数据时,实现数据的分布式存储
分布式存储 是怎么存储数据的?
把数据存储在不同地点的数据库服务器里,每台数据库里存储的数据各不相同
分库/分表
水平分割
垂直分割
mycat支持提供10中分片规则
主要讲的是
枚举分片规则 sharding-by-infile
求模分片规则
使用分片字段的值与指定 的数字做取余计算 根据余数存储数据到后端的数据库服务器里
使用求模分片规则存储数据的表里必须有名称叫id的表头(分片字段)
<table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile" />
<table name="customer" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile">
sharding-by-intfile 分片规则的配置文件
vim /usr/local/mycat/conf/partition-hash-int.txt # 定义分片字段的值
10000=0 0代表dn1数据库 51 10000代表分片字段的值
10010=1 1代表dn2数据库 52
10020=2 # 手动添加,这是第三台主机
/usr/local/mycat/bin/mycat restart
ss -tunlp | grep 8066 # 一定要检查端口
# 如果没查到端口,直接去查看/usr/local/mycat/logs/wrapper.log 日志文件
在客户端50连接mycat服务建表
说明:执行任何命令都要use TESTDB 库里执行,所有命令直接写表名
mysql -h192.168.4.57 -P8066 -uroot -p123456
show databases;
use TESTDB
show tables ;
create table employee(sharding_id int, name char(10),basic int );
insert into employee(sharding_id ,name,basic) values (10000,'jin',28000);
insert into employee(sharding_id ,name,basic) values (10020,'tom',12345);
insert into employee(sharding_id ,name,basic) values (10010,'toed',12345);
insert into employee(sharding_id ,name,basic) values (10030,'to',12345) # can't find any valid datanode :EMPLOYEE -> SHARDING_ID -> 10030这个就不能存储了,因为分片规则里面没有10030的值
# 接下来在每台数据库服务器上面查看数据 ,就会发现每台服务器个一行
select * from db1.employee;
select * from db2.employee;
select * from db3.employee;
查看使用求模分片规则的表
<table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"
rule="mod-long" />
创建hotnews的表
mysql -h192.168.4.57 -P8066 -uroot -p123456
show databases;
use TESTDB
show tables ;
create table hotnews(id int, title char(10),comment varchar(100),worker char(10));
# 余数是0的都会往第一台服务器上面存储
insert into hotnews(id ,title,comment,worker) values(3,'a','aaa','AAA'),(6,'b','aaa','fff'),(9,'c','ccc','cccc');
# 余数是1的都会往第二台服务器上面存储
insert into hotnews(id ,title,comment,worker) values(10,'a','aaa','AAA'),(10,'b','aaa','fff'),(10,'c','ccc','cccc');
# 依此类推
# 51
select * from db1.hotnews;
# 52
select * from db2.hotnews;
# 53
select * from db3.hotnews; # 因为没有余数是2的,所以第三个数据库是没有数据的
工作过程
ls /usr/local/mycat
bin # mycat命令
catlet # 扩展功能
conf # 配置文件
lib # mycat使用的jar包
logs # mycat启动日志和运行日志
wrapper,log # mycat服务启动日志
mycat.log # 记录SQL脚本执行后的报错内容
# 重要配置文件说明
server.xml # 设置连接账号与逻辑库
schema.xml # 配置数据分片存储的表
rule.xml # 分片规则
其他文件 # 分片规则配置文件
第一步: 配置分片服务器57,具体操作如下
# 安装软件
# 了解安装文件列表
# 配置数据库服务器
# 启动mycat服务 并查看服务器状态
# 57
scp -r /linux-soft/4/mysql/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz 192.168.4.57:/root
systemctl stop mysqld.service
systemctl disable mysqld.service
# 因为mycat是用java编写的所以需要安装jdk软件
# 而且版本有要求
yum list | grep openjdk.x
yum -y install java-1.8.0-openjdk.x86_64 # 因为mycat 的版本所以需要的是这个版本
tar xf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
mv mycat/ /usr/local/
ls /usr/local/mycat/ # 通过修改下面的文件来达到分片处理
cat /usr/local/mycat/version.txt # 查看软件的说明信息
/usr/local/mycat/log
/usr/local/mycat/lib/ # 存放的是java脚本,不能动的
/usr/local/mycat/conf/ # 存放的是配置文件,一共有三种类型的配置文件
# .xml 是mycat的主配置文件
# .txt 和 .properties 都是分片规则的配置文件,不同的名称就是不同的分片规则
# .conf
/usr/local/mycat/catlet/ # 就是与其他软件协同工作存放文件的目录
/usr/local/mycat/bin/ # 主要操作的是mycat这个文件
# /usr/local/mycat/bin/mycat --help 查看主要的操作步骤
# 修改配置文件(修改两项)
定义客户端连接mycat服务使用的用户名、密码、虚拟库名(修改配置文件所在的目录/usr/local/mycat/conf/server.xml,这个文件使用默认配置即可,不需要修改)xml是扩展标记语言,就是需要成对出现 要有开始,要有闭合
# 定义用户的是 ····· 这就表明是一个用户
# 注释符号
# 第二个是修改 /usr/local/mycat/conf/schema.xml 这个文件是极其重要的
# 定义数据分片存储数据的表,及使用的分片规则
user 枚举分片规则 就是在这里修改的
在没有修改之前看一下这个文件的语法规则,,头两行内容是不能动的,动了会起不来服务
所有的配置想都是要在<mycat:schema .....> <mycat:schema>
这对标签里面
在配置里面的三项配置
# 定义存储数据的表名和使用的分片规则
<schema name..> </schema>
# 定义数据服务器主机名及存储数据的库名
<dataNode ..... /> 单标签
# 定义数据库的IP地址
<dataHost....> </dataHost>
这个文件里面是有读写分离的配置的
wc -l /usr/local/mycat/conf/schema.xml 查看里面有77行
vim /usr/local/mycat/conf/schema.xml
# 删除56-77行的内容,删除部分都是注释
sed -i '56,77d' /usr/local/mycat/conf/schema.xml
sed -i '16,18d' /usr/local/mycat/conf/schema.xml
cp /usr/local/mycat/conf/schema.xml /root # 备份文件
# 开始修给数据的第一项
<table> 这个标签是指定表的
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
# 将里面的表后面每与后dataNode没有dn3的都添加上dn3,其他项不需要修改
# 定义数据库服务器的定义数据库
修改
<dataNode name="dn1" dataHost="mysql51" database="db1" />
<dataNode name="dn2" dataHost="mysql52" database="db2" />
<dataNode name="dn3" dataHost="mysql53" database="db3" />
dataHost="mysql51" # 这里的名称是可以随意的,但是一般是以主机名指定
database="db1" # 接下来需要在51 上面创建db1的数据库
# 定义数据库服务器的IP
删除单标签的<writeHost>u<readHost>
删除完了之后就是这些
<dataHost name="mysql51" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.4.51:3306" user="pljadmin"
password="123qqq...A">
</writeHost>
</dataHost>
最终修给了name="mysql51" host="hostM1"# 这个说明是第一台主机
url="192.168.4.51:3306" user="pljadmin" password="123qqq...A"
# 配置数据库服务器(51,52,53)添加schema.aml文件中设置内容
create database db1 ; 51
create database db2 ; 52
create database db3 ; 53
grant all on *.* to pljadmin@'%' identified by '123qqq...A'; 51 52 53
以上数据库的内容就配置完了
# 接下来就是启动mycat服务
# 准备工作 定义主机名
把57的物理内存调制到1G以上,不然会带不动mycat
检查3台数据库服务器的授权信息pljadmin
which mariadb || yum -y install mariadb
mysql -h192.168.4.51 -upljadmin -p123qqq...A
mysql -h192.168.4.52 -upljadmin -p123qqq...A
mysql -h192.168.4.53 -upljadmin -p123qqq...A
检查完三个用户,才能开启mycat
ls /user/local/mycat/logs/ 没有启动的时候,没有日志消息的
/usr/local/mycat/bin/mycat start 启动mycat
ss -tunlp | grep 8066
ls /user/local/mycat/logs/ # 启动之后就可以看的到有日志文件了
# 如果启动了。没有查看到端口的话,就查看/user/local/mycat/logs/waepper.log 日志文件
# 测试
# 在客户端50连接mycat服务查看存储数据的表
mysql -h192.168.4.57 -P8066 -uroot -p123456
show databases; 就可以看到假的库名
show tables ; 就可以查看到在/usr/local/mycat/conf/schema.xml文件里面设置的表了
服务器配置
注意:分布式存储数据,表名是不允许重复的
例子:想gamedb库下的user 表存储数据时,把数据分别存储在51、52、53服务器上
第一步:添加新库
第二步:添加新表
第三步:重启mycat
第四部:客户端mycat服务建表存储数据
第五步:
vim /usr/local/mycat/conf/server.xml
<user name="root">
<property name="password">123456</property>
<property name="schemas">TESTDB,GAMEDB</property>
</user>
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB,GAMEDB</property>
<property name="readOnly">true</property>
</user>
vim /usr/local/mycat/conf/schema.xml # 手动添加一个数据库
<schema name="GAMEDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="user" rule="mod-long" dataNode="dn1,dn2,dn3"/>
</schema>
/usr/local/mycat/bin/mycat restart
ss -tunlp | grep 8066
# 客户端50
mysql -h192.168.4.57 -P8066 -uroot -p123456
show databases ;
use GAMEDB;
show tables;
create table user(id int ,name char(10),password char(6));
# 余数是2 ,所以直接在53上面查看数据
insert into user(id,name ,password) values(5,"a","aaa"),(5,"b","bbb");
# 53
select * from db3.user ;
什么是集群? 多台服务器一起提供相同的服务 比如提供网站服务 就是web集群 再比如提供数据库服务 就是数据库集群 比如提供的内存存储服务 就是缓存集群
集群的类型?
高性能(HPI) 高可用 负载均衡集权(LB)
负载均衡集群
高可用集群 集群中的服务器是怎么工作的?
高性能集群
如果默认情况 relay_log_purge=1 时,SQL 线程就会自动将之前的 relay log 全部删除。而当 relay_log_purge=0 时,旧的 relay log 则会被保留。虽然这并不会影响从库复制本身,但还是会有地雷:
集群搭建准备
51、52、53 数据服务器分别启用半同步复制
开启自动
集群环境准备
所有数据库服务器做公共配置(51、52、53)
创建集群
验证集群功能
把宕机的数据库服务器在添加到集群里
# 51、52、53
vim /etc/my.cnf
[mysqld]
validate_password_policy=0
validate_password_length=6
plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so;"
rpl_semi_sync_master_enabled=1
rpl_semi_sync_slave_enabled=1
server_id=51 # 这里的51 是根主机IP写的,也可以随便写
log_bin=master51 # 这里的51 是根主机IP写的,也可以随便写
relay_log_purge=0 #禁止自动删除本机的中继日志文件
systemctl restart mysqld
mysql -uroot -p123456
grant replication slave on *.* to repluser@'%' identified by '123456';
select * from mysql.user \G
# 配置面秘登录 配置ssh
# 所有数据库服务器之间免密登录
# 管理主机能够免密登录所有数据库
# 所有主机都要操作的步骤 # 57 也需要做作,可以无密码登录51 52 53
ssh-keygen
ssh-copy-id 192.168.4.51 52 53
# 配置mysql一主多从结构
51配置为master服务器
52配置slave服务器
53 配置slave服务器
启用binlog日志文件 用户授权
从服务器 制定serverid 数据库管理员登录制定主服务器信息 启动slave
# 51
mysql -uroot -p123456
show master status ;
# 52 53
mysql -uroot -p123456
change master to master_host='192.168.4.51', master_user='repluser',master_password='123456',master_log_file='master51.000001',master_log_pos=441;
start slave;
show slave status \G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
# 一主两从配置完成了
# 创建集群 配置管理主机(57) 配置数据库服务器(51、52、53) 测试配置 验证集群功能
# 57 安装软件 (先安装依赖包) 创建并修改主配置文件 创建故障切换脚本
scp -r /linux-soft/4/mysql/mha-soft-student 192.168.4.57:/root
# yum源需要配置好
cd mha-soft-student/
app1.cnf master_ip_failover 是事先写好的配置文件
perl 开头的是依赖软件
yum -y install perl-*.rpm # yum没有的
yum -y install ExtUtils-* perl-CPAN* # 这个是yum里面有的
tar xf mha4mysql-manager-0.56.tar.gz
cd mha4mysql-manager-0.56/
perl Makefile.PL # 发现有两个包没有
yum list | grep -i perl | grep -i mysql
yum -y install perl-DBD-MySQL.x86_64
yum -y install mha4mysql-node-0.56-0.el6.noarch.rpm
cd mha4mysql-manager-0.56/
perl Makefile.PL # 可以了 这个是解压源码
make && make install # 安装 masterha_ tab键 可以tab出来 就说明安装成功了 这个是管理软件
# 创建并修改管理服务的主配置文件
mkdir /etc/mha # 创建工作目录
cd mha-soft-student/mha4mysql-manager-0.56/ #拷贝主配置文件的模板到工作目录下
cp samples/conf/app1.cnf /etc/mha/
vim /etc/mha/app1.cnf
[server default] # 管理服务运行配置参数
manager_workdir=/etc/mha # 工作目录
manager_log=/etc/mha/manager.log # 日志文件
# 故障切换脚本
master_ip_failover_script=/etc/mha/master_ip_failover
# 免密登录的用户和端口
ssh_user=root
ssh_port=22
# 拷贝binlog日志命令时候的连接用户
repl_user=repluser
repl_password=123456
# 监控数据库服务状态时候的用户 监控用户
user=plj
password=123456
[server1] # 第一台数据库服务器
hostname=192.168.4.51
port=3306
candidate_master=1 # 竞选主服务器
[server2] # 第二台数据库服务器
hostname=192.168.4.52
port=3306
candidate_master=1
[server3] # 第三太数据库服务器
hostname=192.168.4.53
port=3306
candidate_master=1
# 创建故障切换脚本
cp /root/mha-soft-student/master_ip_failover /etc/mha/ # 将写好的脚本拷贝
chmod +x /etc/mha/master_ip_failover
# 指定ip地址及地址部署在那块网卡上
# 注意 :网卡名要根据数据库使用的网卡名填写
vim +35 /etc/mha/master_ip_failover
my $vip = '192.168.4.100/24'; # Virtual IP
my $key = "1";
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip"; # 部署vip地址
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down"; # 释放vip地址
# 配置数据库服务器(51、52、53)
# 根据vip 地址部署在当前mysqld主从结构中的主数据库服务器51上
# 51
ifconfig eth0
ifconfig eth0:1 192.168.4.100/24 # 添加虚拟IP 临时的虚拟IP 因为是虚拟IP,必须是临时的
# 如果添加错误了,需要在真机上面去掉 ifdown eth0:1
# 创建监控用户plj (51\52\53)
grant all on *.* to plj@'%' identified by '123456'; # 在主数据库服务器添加,从会自动添加
# 52.53
select user from mysql.user ; # 可以查看到用户
# 测试配置 说明: 要求环境准备是对的 关路主机的appl.cnf文件是正确的 数据库服务器的配置是正确的 如果不对,测试命令会输出相应的报错信息
# 57
masterha_check_ssh --conf=/etc/mha/app1.cnf # 测试免密登录
masterha_check_repl --conf=/etc/mha/app1.cnf # 测试mysqld主从同步
# 测试没过 /usr/local/share/perl5/MHA/MasterMonitor.pm line 374
# 所有数据库服务器上安装mha_node 软件
scp -r /linux-soft/4/mysql/mha-soft-student 192.168.4.53:/root # 51/52/53
cd mha-soft-student/
yum -y install perl-*.rpm # 安装依赖环境
yum -y install mha4mysql-node-0.56-0.el6.noarch.rpm
masterha_check_repl --conf=/etc/mha/app1.cnf # 再次测试 Health is OK
# 启动管理服务
masterha_manager --conf=/etc/mha/app1.cnf # 默认是占用一个终端显示的
masterha_manager --conf=/etc/mha/app1.cnf & #这样不能保证在后台运行的
nohup masterha_manager --conf=/etc/mha/app1.cnf & # 这样一定是运行的
masterha_check_status --conf=/etc/mha/app1.cnf # 检查是否运行
jobs # 查看后台运行的程序
kill %1 # 杀掉后台的程序
# nohup
# 用途:不挂断地运行命令。
# 语法:nohup Command [ Arg … ] [ & ]
# 无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup.out 文件中。
# 如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。
# 如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。
# 退出状态:该命令返回下列出口值:
# 126 可以查找但不能调用 Command 参数指定的命令。
# 127 nohup 命令发生错误或不能查找由 Command 参数指定的命令。
# 否则,nohup 命令的退出状态是 Command 参数指定命令的退出状态。
优化参数
--remove_dead_master_conf 把党纪的master服务器的配置在app1.cnf文件里删除
--ignore_last_failover 做多次vip迁移 默认只做一次故障迁移
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover & # 添加优化参数之后再运行程序
# 验证集群功能
# 在主数据库服务添加客户端连接使用的用户和密码
# 客户端连接vip192.168.4.100访问数据库服务
# 存储数据
# 查询数据
# 51 : 从服务器会自定同步了
mysql -uroot -p123456
create database db1;
create table db1.a(id int);
grant select,insert on db1.* to yaya666@'%' identified by '123456';
# 客户端50连接100访问数据库
mysql -h192.168.4.100 -uyaya666 -p123456
select * from db1.a;
insert into db1.a values (1);
# 测试高可用 : 把master角色服务器51的数据库停止 客户端依然可以连接vip访问192.168.4.100进行连接 在app1.cnf文件里面没有[server1] 的配置了, 管理服务会停止 启动查看管理服务的运行状态 启动管理服务会监视新的主数据库服务器 另一台会数据库服务器会自定做新的master服务器的从机
# 把51数据库服务器停止的
systemctl stop mysqld
# 57 检测到51宕机了,就会执行/etc/mha下面的脚本,将vip放到从服务器
masterha_check_status --conf=/etc/mha/app1.cnf
服务状态就会停止了,
# 50
mysql -h192.168.4.100 -uyaya666 -p123456
select * from db1.a;
insert into db1.a values(999);
# 57
cat /etc/mha/app1.cnf # 会发现没有server1的配置了,因为在运行程序的时候加入了优化参数,所以会将配置文件中server1删除 ,主服务器就变成了52,53就变成了52的从服务器了,因为规定MHA集群必须是主从或主从从结构,其他结构的话会报错
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover & # 再将程序开启,
masterha_check_status --conf=/etc/mha/app1.cnf # 再次查看监视的主服务器
# 52 查看vip
ifconfig eth0:1 #就会发现是有虚拟IP
# 53
mysql -uroot -p123456
show slave status \G # 查看masterhost 主是52
# 注意:管理服务监控到当前master服务器宕机后,管理服务会停止
要让管理服务监视新的主服务器,要管理员手动启动管理服务才可以
写一个计划任务去执行监视管理服务的脚本, 脚本的功能发现管理服务停止了,就启动管理服务
*/10 * * * * 每隔十分钟去执行一遍监视管理服务状态的脚本
# 把宕机的数据库服务器51再添加到集群上面
# 想要进集群必须是当前主服务器的从才可以
# 启动51主机的数据库服务器
# 把51配置为当前master服务器slave主机
# 把51主机添加到app1.cnf文件里面
# 测试主从配置
# 重启管理配置
#51
systemctl start mysqld
ss -tunlp | grep 3306
ifconfig eth0:1
mysql -uroot -p123456 -e 'show slave status ;'
# 52 数据完全备份
mysqldump -uroot -p123456 -B db1 > /root/db1.sql
scp /root/db1.sql 192.168.4.51:/root
mysql -uroot -p123456 -e 'show master status ;'
# 51
mysql -uroot -p123456 < /root/db1.sql
mysql -uroot -p123456
change master to master_host='192.168.4.52', master_user='repluser',master_password='123456',master_log_file='master52.000001',master_log_pos=688;
start slave ;
show slave status \G
# 57
vim /etc/mha/app1.cnf
[server1] # 第一台数据库服务器
hostname=192.168.4.51
port=3306
candidate_master=1
masterha_check_status --conf=/etc/mha/app1.cnf
masterha_stop --conf=/etc/mha/app1.cnf # 停止配置服务
jobs
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover & # 重新开启,既是将51添加到集群里面了
masterha_check_status --conf=/etc/mha/app1.cnf # 再次查看主还是52
内置了mysqld服务
服务端口
端口 | 说明 |
---|---|
3306 | 数据库服务端口 |
4444 | SST端口 |
4567 | 集群通信端口 |
4568 | IST端口 |
SST | state snapshot Transfer 全量同步 |
IST | incremental state Transfer 增量同步 |
创建3台新的虚拟机(不安装任何版本的mysqld数据库服务软件)
ip 71 72 73
将pxc拷贝到三台机器上面
scp -r /linux-soft/4/mysql/pxc 192.168.4.73:/root
# 配置PXC mysql高可用集群,具体操作如下
第一步 分别 71 72 73 安装pxc软件
# 注意: 软件之间有以来 所有软件
# 71 72 73
cd pxc/
yum -y install libev-4.15-1.el6.rf.x86_64.rpm percona-xtrabackup-24-2.4.13-1.el7.x86_64.rpm qpress-1.1-14.11.x86_64.rpm # 顺序不能变,相互之间是有依赖的
rm -rf libev-4.15-1.el6.rf.x86_64.rpm percona-xtrabackup-24-2.4.13-1.el7.x86_64.rpm qpress-1.1-14.11.x86_64.rpm
tar xf Percona-XtraDB-Cluster-5.7.25-31.35-r463-el7-x86_64-bundle.tar
yum -y install Percona-XtraDB-*.rpm
# 修给各个配置文件
cd /etc/percona-xtradb-cluster.conf.d/
vim mysqld.cnf
[mysqld]
server-id=71 # 修改为71 以IP为主 指定server-id
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin
log_slave_updates
expire_logs_days=7
# 修改集群配置文件 说明:3台数据库服务器都要修改 其中如下配置项的值必须相同
vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf # 这是集群配置文件,每台服务器都要修改
wsrep_cluster_address=gcomm://192.168.4.71,192.168.4.72,192.168.4.73 # 指定的是成员列表 三台数据库服务器必须是一样的
wsrep_node_address=192.168.4.72 # 25行 # 修改为本机IP地址
wsrep_cluster_name=pxc-cluster # 三台数据库服务器必须是一样的
wsrep_node_name=pxc72 # 指定本机的主机名
wsrep_sst_auth="sstuser:123qqq...A" # 39 用户名跟密码 三台数据库服务器必须是一样的
# 初始化集群信息 说明: 在三台任意一台都可以执行初始化,但是初始滑操作只能执行一遍
# 在71上做集群初始化操作
ls /var/lib/mysql # 空的
systemctl start [email protected] # tab不出来 必须记住
ls /var/lib/mysql
ss -tunlp |grep 3306
ss -tunlp |grep 4567
# 数据库管理员使用初始密码 登录 并强制修改密码
grep password /var/log/mysqld.log
mysql -uroot -p'X1fqsw*ZvJ)='
set password='123456'; # 没有策略要求
show databases;
grant all on *.* to sstuser@'%' identified by '123qqq...A' # 添加配置文件中设置的用户跟密码
# 分别启动72 73主机的数据库服务 服务启动后会自动同步71的所有数据
# 72 要求:配置文件是对的,防火墙和selinux是关闭的
systemctl start mysql # 注意,没有d 第一次同步是全量同步 所以需要的时间比较久 在按黄pxc软件的时候是内置了同步程序了,是通过配置文件去同步的
ls /var/lib/mysql
ss -tunlp |grep 3306
ss -tunlp |grep 4567
mysql -uroot -p123456 # 因为已经同步了,所以用户密码都是一样的
select user from mysql.user ;
# 72 和 73 的操作是一样的
# 测试
# 查看集群信息
# 在任何一台服务器上面都可以查看集群信息
mysql -uroot -p123456
show status like "%wsrep%";
# wsrep_incoming_addresses 192.168.4.72:3306,192.168.4.71:3306,192.168.4.73:3306 集群中一共有这么几台机器
# 连接集群中的任意数据库服务器 查询和存储数据
# 73
create database db1;
create table db1.user(id int primary key auto_increment ,name char(10) ,age int ); # 在PXC存储数据的时候 必须要有主键
grant select ,insert on db1.* to plj@'%' identified by '123456';
# 71 72
mysql -h192.168.4.71 -uplj -p123456 # 使用添加的用户连接服务器 任意一台都是可以的
insert into db1.user(name,age) values ('to45m',12),('o74o',19); # 在PXC集群中 主键的自增的步长可能是小于 3+1 任意一个数 ,集群主机数量加1 ;为了避免数据同步的时候 主键相同
select * from db1.user ; # 发现主键id可能是1,2,3,4
# 测试宕机主机自动加入集群及自动同步宕机期间的数据
# 统一把71数据库停止 (模拟宕机) 说明:71首次停止的是原来的服务
systemctl stop [email protected] # 首次停止服务是这个命令
ss -tunlp |grep 3306
ss -tunlp |grep 4567 # 是没有端口的了 这个是判断是否宕机的端口的
# 在另外两台查看集群信息 存储新数据 (在71宕机期间,存储数据)
# 72
show status like "%wsrep%"; #192.168.4.72:3306,192.168.4.73:3306
insert into db1.user(name,age) values ('yy',12),('opp',19);
# 73
select * from db1.user ;
# 启动71主机数据库 查看集群信息 查看数据
# 71
systemctl start mysql
ss -tunlp |grep 3306
ss -tunlp |grep 4567
mysql -uroot -p123456
show status like "%wsrep%"; # 发现又有三台数据库的IP了
select * from db1.user ; # 数据也同步了
show engines ;
CSV
PERFORMANCE_SCHEMA
BLACKHOLE
MyISAM
InnoDB # 这个后面是defaults 的说明是建设表时候默认的
ARCHIVE
MRG_MYISAM
FEDERATED
MEMORY
# 表头
Comment # 对存储引擎功能的说明
Transactions # 是否支持事务
# 例子
create database db1;
create table db1.enployees(name char(10),class varchar(100));
show create table db1.enployees \G # 就可以查看到存储引擎了,
show create table mysql.user \G # 查看到user 表是myisam存储引擎
# 修改存储的默认存储引擎
vim /etc/my.cnf
default-storage-engine=myisam # 设置默认的存储引擎为myisqm
systemctl restart mysqld
show engines ; # 管理员登录查看结果
create table db1.test (name char(10));
show create table db1.test \G
# 建表时候 ,指定表的存储引擎
create table db1.user12(age int ,name char(10))engine=memory;
show create table db1.user12 \G
# 表的存储引擎不同 数据存储方式不同
show create table mysql.user \G
ls /var/lib/mysql/mysql/user* # 发现是有三个文件的,user.frm user.MY user.MYD
show create tarena.salary \G # innodb
ls /var/lib/mysql/tarena/salary # 发现是有连个文件 salary.frm salary.idb
show create db1.user \G # memory
ls /var/lib/mysql/db1/user12* # 只发现。frm文件
要在没有存储数据之前,修改表的存储引擎
alter table db1.user engine=innodb ;
show create table db1.user ;
ls /var/lib/mysql/db1/user* # 变成了两个文件,就多了一个文件去存储数据
MySQL工作过程
没有好坏之分,看需求
myisam存储引擎的特点
innodb存储引擎的特点
专业术语:
# 演示
mysqldump -uroot -p12346 tarena user > /root/user.sql
vim /root/user.sql
LOCK TABLE `user` WRITE # 这个就是锁表了
UNLOCK TABLES; # 解锁
# 开两个终端
LOCK TABLE `tarena.user` WRITE;
select * frim tarena.user ; # 在另外个终端的操作 就会卡住了
UNLOCK TABLES; # 另外个终端才会执行sql命令
# 什么叫一致性
insert into tarena.user (name ) values ('aa'); 没回车之前,所有人都是看不到数据的,回车后,才可以查看的到
# 当有两个人同时操作表,是互相不知道对方操作什么的,这个就是隔离性
对事物做管理的命令
命令 | 作用 |
---|---|
begin或start transaction | 显示开启一个事务 |
commit | 提交事务 |
rollback | 回滚事务 |
savepoint 名称 | 在事务里创建保存点(可以创建多个) |
release savepoint 名称 | 删除保存点 |
rollback to 保存点 | 把事务回滚到保存点 |
set transaction | 设置事务隔离级别 |
set autocommit=0/1 | 关闭/启动自动提交 |
select @@tx_isolation | 查看当前事务隔离级别 |
show vartables like “autocommit” | 查看自动提交状态 |
insert into tarena.user(name) values('AAA'); # 一按下就提交了
shwo variables like "autocommit" # 默认是开启的,就是命令一敲下就直接提交了
set autocommit=0; # 关闭自动提交功能 ,所以需要每次都需要提交
# 事物是对数据生效的
create table tareana.t33(id int )engine=innodb;
insert into tarena.t33 values (101);
select * from tarena.t33; # 在自己这里是可以查看到的,
# 打开另外一终端查看是查看不到的,这个就是隔离性了
commit; # 这样事务才算是结束 这就是事务的一致性和隔离性的效果
# 演示事务回滚
delete from tarena.t33; # 在自己这里看是看到记录是已经删除的,但是在另外终端是还有数据的
roolback #事务的回滚 ,数据记录就回来了
# 如果删除之后,马上commit的话,是不会回滚的
# 断开连接再登录就已经是还原的了自动提交功能
读未提交:最低的隔离级别,允许读取尚未提交的数据变更;可能会导致脏读、幻读、不可重复读
读提交:允许并发事务读取已经提交的数据,可以阻止脏读;但幻读或不可重复读仍有可能发生
可重复读:对同一字段的多次读取结果都是一致的;除非数据是被本身事务自己所修改;可以阻止脏读和不可重复读,但幻读仍有可能发生
序列化:最高 隔离级别,完全俯冲ACID的隔离级别。所有的事务依次逐个执行,事务之间完全不可能产生干扰。该级别可以防止脏读和不可重复读,及幻读。
级别越高,处理效果越底
从上到下,隔离强度逐渐增强,向能逐渐变差。采用那种隔离级别要根据系统需要权衡决定,其中,可重复读就是MySQL的默认级别
# 两个终端
select @@tx_isolation; # 默认是可重复读的级别
set auot_commit=0 # 关闭自动提交 1
set session transaction isolation level read uncommitted # 设置其他人的隔离级别为读未提交 2
select @@tx_isolation;# 2
select * from tarena.t33 ; #1
insert into tarena.t33 values (8888) ; #1
select * from tarena.t33 ;#2 就会发现是1没提交的数据了,
rollback ;#1 事务回滚
select * from tarena.t33 ;#2 就发现没有数据了,这就是脏读了,因为对方是没有提交的
# 可重复读
select * from tarena.t33 ; #1
insert into tarena.t33 values (8888);#1
select * from tarena.t33 ;#2 是查看不了的
innodb 使用
myisam 适用
关系型数据库服务管理系统 (RDMS)
非关系型数据库服务管理系统 (NoSQL)
软件有那些?
存储数据的特点是什么?
Redis
Remote Dictionary server(远程字典服务器)
是一款高性能的(key/alues)分布式内存数据库
支持数据持久化(定期把内存里数据存储到硬盘)
支持多种数据类型:字符、列表、散列、集合
支持master-salve模式数据备份
# 在50主机上面部署redis
scp -r /linux-soft/4/redis/redis-4.0.8.tar.gz 192.168.4.50:/root
yum -y install gcc
tar xf redis-4.0.8.tar.gz
cd redis-4.0.8/ # 已经有编译完成了Makefile
make && make install
redis- <tab>两下
# redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server
# 初始化配置(确认服务的配置项)
# 说明:初始化配置完成后 会启动redis服务 并设置为开机运行
# 进到源码目录里面[root@localhost redis-4.0.8]#
./utils/install_server.sh # 确认端口 redis主配置文件 服务的日志位置 redis数据库目录 启动时候启动的命令 @@ 一路回车
Selected config:
Port : 6379 # 确认端口
Config file : /etc/redis/6379.conf # redis主配置文件
Log file : /var/log/redis_6379.log # 服务的日志位置
Data dir : /var/lib/redis/6379 # redis数据库目录
Executable : /usr/local/bin/redis-server # 启动时候启动的命令
Cli Executable : /usr/local/bin/redis-cli # 命令行连接命令
ss -tunlp | grep 6379 # 查看端口 127.0.0.1:6379 (默认的情况下是回环地址)
# 连接服务 redis-cli 默认连接本机的redis服务
redis-cli # 登录
ping
set school tarena
keys * # 查看所有的变量
get school # 获取school的值
/etc/init.d/redis_6379 stop # 停止服务
/etc/init.d/redis_6379 start # 启动服务
# 都是需要修改配置文件来实现的
/etc/init.d/redis_6379 stop # 把按默认配置先停止服务
vim /etc/redis/6379.conf # 主配置文件
port 6379 # 93 # 可以将端口更改为6350
bind 192.168.4.50 # 70 将回环地址配置为主机IP地址
requirepass foobared # 501 foobared是密码 修改为123456
/etc/init.d/redis_6379 start
ss -tunlp | grep 6350 # 检查已经更改的端口
# 指定配置
redis-cli -h 192.168.4.50 -p 6350 -a 123456
set name plj
keys *
/etc/init.d/redis_6379 stop # 接着上面的,发现停不下来
redis-cli -h 192.168.4.50 -p 6350 -a 123456 shutdown # 指定使用命令停止了
ss -tunlp | grep 6350 # 查不到端口
/etc/init.d/redis_6379 start # 启动服务还是可以使用默认配置启用服务
实验的诉求:那nginx 网站的数据存储到50主机redis服务器里面
第一步: 部署nginx网站服务器,具体操作如下
# 安装nginx依赖包
# 安装源码nginx
# 修改nginx配置文件
# 启动nginx 服务
# 安装php相关软件
# 启动php-fpm服务
# 测试配置
scp -r /linux-soft/4/redis/lnmp/nginx-1.12.2.tar.gz /linux-soft/4/redis/lnmp/php-redis-2.2.4.tar.gz /linux-soft/4/redis/lnmp/linkredis.php 192.168.4.51:/root
yum -y install gcc pcre-devel zlib-devel
tar xf nginx-1.12.2.tar.gz
cd nginx-1.12.2/
./configure && make && make install
ls /usr/local/nginx
cd /usr/local/nginx
vim +65 conf/nginx.conf
sbin/nginx
ss -tunlp | grep 80
yum -y install php php-fpm php-devel
systemctl start php-fpm
ss -tunlp | grep 9000
vim /usr/local/nginx/html/test.php
<?php
$i=99
echo $i
?>
curl http://localhost/test.php
ss -tunlp | grep 6350 #50
/etc/init.d/redis_6379 start # 如果没有开启的话
redis-cli -h 192.168.4.50 -p 6350 -a 123456 # 检查昨天的数据是否还在
KEYS * # 发现数据是还在的 这个就是说明Redis 的持久性
ss -tunlp | grep 80 # 51 检查nginx的服务是否起来
ss -tnulp|grep 9000 # 51 检查php-fpm的服务是否起来
curl http://localhost/test.php # 51 检查昨天的写的脚本
# LNP + Redis
配置51主机的php支持redis服务 (默认是不支持的)
php -m # 查看php支持相应的功能模块
php -m | grep redis # 发现是没有的
# 安装提供redis模块的软件
# 调用模块 php-redis-2.2.4.tar.gz
tar xf php-redis-2.2.4.tar.gz
cd phpredis-2.2.4/
phpize # 生成php配置程序的文件 生成了configure
ls /usr/bin/php-config
./configure --with-php-config=/usr/bin/php-config
make && make install # 安装的输出信息要注意一下
/usr/lib64/php/modules/ # 说明 功能模块是放在这个目录下面的
当前php没有调用的,需要去修改配置文件才能调用
vim +728 /etc/php.ini # php的进程配置文件
extension_dir = "/usr/lib64/php/modules/" # 去掉# 后面的路径改为模块所在的路径
extension= "redis.so" 模块是没有下划线制定dir的
systemctl restart php-fpm
php -m | grep redis # 发现是出现有支持redis 模块的了
# 测试配置 (编写连接redis 服务存储数据的脚本)工作环境中是脚本是程序员写的
cp linkredis.php /usr/local/nginx/html/test2.php
vim /usr/local/nginx/html/test2.php
<?php
$redis = new redis(); # 创建连接名令;也就是调用模块
$redis->connect('192.168.4.50',6350); # 用模块连接数据库服务器
$redis->auth("123456"); # 指定连接的密码
$redis->set('redistest','666666'); # 输入数据
echo $redis->get('redistest'); # 获取数据
?>
# 在客户端访问网站的php脚本
curl http://localhost/test2.php
# 在redis服务器本机查看内存数据
redis-cli -h 192.168.4.50 -p 6350 -a 123456 # 50 登录redis查看数据
KEYS * # 50 可以查看到数据
GET redistest # 查看values
set key名 key值 # 存储1个key值
mset key名列表 # 存储多个key值
get key名 # 获取key值
mget # 获取多个key值
select 数据库编号0-15 # 切换库
keys * # 显示所有key名
keys a? # 显示指定key名
exists` key名 # 测试key名是否存在 0/1
ttl key名 # 查看key生存时间 -1 : 是永久
type key名 # 查看key类型
move key名 库型号 # 移动key到指定库
expire key名 数字 # 设置key有效时间
del key名 # 删除指定的key
flushall # 删除内存里所有的key
flushdb # 删除所有库的所有key
save # 保存所有key到硬盘
shutdown # 停止服务
/etc/redis/6379.conf
名称 | 说明 |
---|---|
netword | 网络 |
general | 常规 |
snapshotting | 快照 |
replication | 复制 |
security | 安全 |
clients | 客户端 |
memory managenent | 内存管理 |
常用的配置项
内存清楚策略:向内存存储数据时候,若存储空间不足删除内存里已有数据的方式
内存空间不足时,删除已存储
vim /etc/redis/6379.conf # 找到MAXMEMORY POLICY
# 文件下面就有内存清除策略了5类 564左右
策略分类 | 说明 | 名称 | 删除范围 |
---|---|---|---|
LRU | 删除最近最少使用 | volatile-lru | 针对设置了TTL的key |
allkeys-lru | 针对所有的key | ||
LFU | 删除使用频率最少 | volatile-lfu | 针对设置了TTL的key |
allkeys-lfu | 针对所有的key | ||
RANDOM | 随机删除 | volatile-random | 针对设置了TTL的key |
allkeys-random | 针对所有的key | ||
volatile-ttl | 删除快要过期的 | ||
noeviction | 不删除 |
vim /etc/redis/6379.conf # 大概在591行左右
maxmemory-policy 策略方式
maxmemory //最大内存
maxmemory-policy //定义使用策略
maxmemory-samples //选取key模板个数(针对lru和ttl和lfu策略)
# 主机上面部署redis
for i in 51 52 53 54 56 ; do scp -r /linux-soft/4/redis/redis-4.0.8.tar.gz 192.168.4.$i:/root && ssh 192.168.4.$i && yum -y install gcc && tar xf redis-4.0.8.tar.gz && cd redis-4.0.8/ && make && make install ;done
./utils/install_server.sh
ss -tunlp | grep 6379
/etc/init.d/redis_6379 stop
vim /etc/redis/6379.conf
bind 192.168.4.50 # 70 将回环地址配置为主机IP地址
cluster-enabled yes # 815 启动集群功能
cluster-node-timeout 5000 #829 超时时间毫秒
/etc/init.d/redis_6379 start
ss -tunlp | grep redis-server # 检查会发现有两个端口
sed -i '70c bind 192\.168\.4\.51' /etc/redis/6379.conf && sed -i '815c cluster-enabled yes' /etc/redis/6379.conf && sed -i '829c cluster-node-timeout 5000' /etc/redis/6379.conf && sed -i '823c cluster-config-file nodes-6379.conf' /etc/redis/6379.conf
命令 | 描述 |
---|---|
create | 创建集群 |
check | 检查集群 |
info | 查看集群信息 |
reshard | 重新分片 |
del-node | 删除主机 |
add-node --salve | 添加slave主机 |
add-node | 添加master主机 |
rebalance | 平均分配hash slots |
# 创建集群
# 配置管理集群主机192.168.4.57
# 准备ruby脚本运行环境
yum -y install ruby
scp /linux-soft/4/redis/redis-3.2.1.gem /linux-soft/4/redis/redis-4.0.8.tar.gz 192.168.4.57:/root # 脚本 和源码包
which gem || yum -y install rubygems
gem install redis-3.2.1.gem # 当前目录下面的gem包
# 创建ruby脚本
tar xf redis-4.0.8.tar.gz
cd redis-4.0.8/ && ls src/*.rb
mkdir /root/bin # 创建命令检索目录
cp /root/redis-4.0.8/src/redis-trib.rb /root/bin # 创建管理集群脚本
redis-trib.rb help # 查看命令帮助
# 查看集群状态
redis-cli -h 192.168.4.51 -p 6379 # 51
192.168.4.51:6379> CLUSTER INFO
# cluster_state:fail # 如果在集群里面的话是ok状态
# 在管理主机创建集群
# 注意:51~57 主机防火墙和selinux必须关闭
# redis 服务器51~56 内存里不允许有数据
# redis服务器51~56
#创建集群的命令格式 57主机
redis-trib.rb create --replicas 数字 //从数据库服务器的台数 redis服务器列表
说明
--replicas 数字 //从数据库服务器的台数
默认创建集群时候,默认会把redis服务器列表中前3台数据库配置为master服务器 redis服务器列表中其他服务器做salve服务器
redis-trib.rb create --replicas 1 192.168.4.51:6379 192.168.4.52:6379 192.168.4.53:6379 192.168.4.54:6379 192.168.4.55:6379 192.168.4.56:6379 # 意思就是一共是有三台主服务器和每台数据库服务器只有一个从服务器 服务器一定是3的整数倍
[OK] All 16384 slots covered. # 意思是 16384个hash槽分配完毕
redis-trib.rb info 192.168.4.51:6379 # 查看集群信息
# 在管理主机查看集群详细信息
redis-trib.rb check 192.168.4.51:6379
# M 主服务器 后面的是id 下面的一行有标名slots 0~5460个槽
# S 从服务器 后面的是id
# 在redis数据库服务器本机查看集群信息 如51主机
192.168.4.51:6379> CLUSTER INFO
cluster_state:ok 查看说明在集群里面的了
# 访问集群验证集群功能
!!!redis集群的功能,如下:
# 数据是分布式存储的
# 能实现服务高可用,主从结构中的主宕机后slave服务器自动升级为master 宕机的服务器恢复后 自动加入集群 并做当前主服务器的slave主机,自动同步宕机期间的数据。
# 数据自动备份
# 访问集群的命令格式 会根据集群算法的计算结果把数据存储在master服务器上
redis-cli -c -h 集群中任意主机的ip -p 端口号 # -c 连接集群中的redis服务器,会自定调用集群算法存储数据
# 集群存储数据的工作原理
访问客户端
例子 : 在50主机连接集群存储
redis-cli -c -h 192.168.4.52 -p 6379 # 因为之前50有安装过redis,所有有这个命令
192.168.4.52:6379> INFO replication # 检查当前主机的集群角色
# Replication
role:master
connected_slaves:1 # 这个代表有一个从
192.168.4.56:6379> INFO replication # 检查当前主机的集群角色
# Replication
role:slave
master_host:192.168.4.52 # 这个代表是主服务器的IP
192.168.4.53:6379> set name aa # 53
-> Redirected to slot [5798] located at 192.168.4.52:6379 # 根据集群的计算结果存储到52上面
[root@57 ~]# redis-trib.rb info 192.168.4.51:6379
192.168.4.53:6379 (e5edbde6...) -> 0 keys | 5461 slots | 1 slaves.
192.168.4.55:6379 (ac6b607d...) -> 0 keys | 5461 slots | 1 slaves.
192.168.4.52:6379 (f9820a19...) -> 1 keys | 5462 slots | 1 slaves.
192.168.4.53:6379> set q 0
192.168.4.53:6379> set z 12 # 根据集群计算结果在那个slot槽范围内 就存储在那个数据库上面
-> Redirected to slot [8157] located at 192.168.4.52:6379
192.168.4.52:6379> KEYS *
1) "z"
192.168.4.52:6379> set v1 101
-> Redirected to slot [1165] located at 192.168.4.55:6379
192.168.4.55:6379> KEYS *
1) "v1"
# 槽越多,能存到该数据库的概率就越大 数据越大,表明存储到这个数据库的机会就越大
# 槽 是可以规定大小的 ,在配置集群的时候可以分配的,如果说,内存很大的话,可以重新分片
通知master主机 的redis服务
检测集群
在管理主机查看信息
测试高可用
# 没有停止之前在管理主机查看集群信息
[root@57 ~]# redis-trib.rb info 192.168.4.51:6379
192.168.4.51:6379 (0e30fdd2...) -> 0 keys | 5461 slots | 1 slaves.
192.168.4.52:6379 (f9820a19...) -> 1 keys | 5462 slots | 1 slaves.
192.168.4.53:6379 (e5edbde6...) -> 0 keys | 5461 slots | 1 slaves.
# 把master角色之际的redis服务停止
[root@51 ~]# redis-cli -h 192.168.4.51 -p 6379 shutdown
[root@51 ~]# ss -tunlp | grep redis
# 在管理主机查看集群信息 # 发现是少了一台从数据库服务器了
redis-trib.rb info 192.168.4.52:6379
192.168.4.52:6379 (f9820a19...) -> 1 keys | 5462 slots | 1 slaves.
192.168.4.55:6379 (ac6b607d...) -> 0 keys | 5461 slots | 0 slaves.
192.168.4.53:6379 (e5edbde6...) -> 0 keys | 5461 slots | 1 slaves.
# 启动宕机服务
/etc/init.d/redis_6379 start # 将51redis数据库重新启动
ss -tunlp | grep redis # 查询到两个端口
# 在管理主机查看集群信息
[root@57 ~]# redis-trib.rb info 192.168.4.52:6379 # 从数据库就会自动加入集群中
192.168.4.52:6379 (f9820a19...) -> 1 keys | 5462 slots | 1 slaves.
192.168.4.55:6379 (ac6b607d...) -> 0 keys | 5461 slots | 1 slaves.
192.168.4.53:6379 (e5edbde6...) -> 0 keys | 5461 slots | 1 slaves.
说明: 什么情况下需要向集群里添加新主机(新添加master角色服务器)
redis-trib.rb add-node 新主机Ip:端口 集群中已有主机的ip:端口
命令格式
重新分片
说明: 从角色服务器的数据是master服务器同步过来的数据
所以slave角色的服务器不需要分配hash slots 只要把主机添加到集群了所slots服务器就可以
edis-trib.rb add-node --slave 新主机Ip:端口 集群中已有主机的ip:端口
诉求:把redus服务器59添加到58的slvae服务器
会自动做从服务器个数最少的master服务器的从服务器
配置一台新redis服务器
添加slave
添加主机
添加master角色主机到集群里
1. 准备一台启用了集群功能的redis服务器
创建新虚拟机配置ip地址为192.168.58 安装redis服务软件 初始化配置
停止服务 修改IP地址 启用集群功能 启用redis服务
scp -r /linux-soft/4/redis/redis-4.0.8.tar.gz 192.168.4.58:/root
yum -y install gcc && tar xf redis-4.0.8.tar.gz && cd redis-4.0.8/ && make && make install
./utils/install_server.sh
ss -tunlp | grep 6379
/etc/init.d/redis_6379 stop
sed -i '70c bind 192\.168\.4\.51' /etc/redis/6379.conf && sed -i '815c cluster-enabled yes' /etc/redis/6379.conf && sed -i '829c cluster-node-timeout 5000' /etc/redis/6379.conf && sed -i '823c cluster-config-file nodes-6379.conf' /etc/redis/6379.conf
/etc/init.d/redis_6379 start
ss -tunlp | grep redis-server # 检查会发现有两个端口
2. 在管理主机57把新主机58加到集群里
把58主机添加到集群里面
添加master角色主机的命令格式
redis-trib.rb add-node 新主机IP:端口号 集群中已有主机的IP:端口号
# redis-trib.rb add-node 192.168.4.58:6379 192.168.4.53:6379
# [OK] New node added correctly. 显示添加成功
redis-trib.rb info 192.168.4.53:6379 # 发现是没有hash槽 ,这样子就不会有存储数据的机会 ,还有一个风险就是单点故障,没有从机
给58主机分配hash槽
添加到集群里面master分配hash槽
因为没有hash槽得不到存储数据的机会。
想一下分配多少个hash槽给 58 主机使用合理? 16384/4 = 4096
从当前3台主服务器里 各自拿出一部分hash槽给 58 主机
[root@host57 ~]# redis-trib.rb reshard 192.168.4.53:6379
How many slots do you want to move (from 1 to 16384)?4096
What is the receiving node ID? 主数据库服务器的ID
Source Node: ALL (表示当前所有主服务器一起凑够4096个hash槽 给 新的主服务器)
Do you want to proceed with the proposed reshard plan (yes/no)? yes 同意
命令格式[root@mgm57 ~]# redis-trib.rb del-node 集群中任意主机的Ip:端口 被移除主机的id
说明: slave角色的主机没有hash slots 直接移出就可以 主机被遗嘱集群后 redis服务自动停止
3.2.2 移除master角色的主机
说明:master角色的服务器会占用hash slots 要先释放hash slots 再执行移除主机的命令
具体操作步骤:
第一步:释放 hash slots (再次执行reshard命令)
第二步:移除主机 (执行删除主机的命令)
诉求把master角色 主机 host58移除集群,在管理主机mgm57 做如下操作:
#释放 hash slots (再次执行reshard命令)
[root@mgm57 ~]# redis-trib.rb reshard 192.168.4.56:6379
第1个问题:释放hash slots 的个数
How many slots do you want to move (from 1 to 16384)? 4096 (host58主机占用hash slots 的个数)
第2个问题:接收4096的个hash slots的主数据库服务器的ID (随便给那个主服务器都可以)
What is the receiving node ID?0eb3b7aa0493a19189cba35b0c658202cc20884b (host51主机的id ,就是把释放的4096个hash slots给主数据库服务器host51)
第3个问题:从那台主服务器移除4096个hash slots
Source node #1:87cc1c128166e08a16cc294758611453bbc71437 (host58主机的id)
Source node #2:done 结束指定
第4个问题:确认配置 yes同意 no 退出
Do you want to proceed with the proposed reshard plan (yes/no)? yes 同意
查看集群信息(发现host51 主服务器hash slots变多了 )
[root@mgm57 ~]# redis-trib.rb info 192.168.4.56:6379
192.168.4.53:6379 (f2c1bdb7...) -> 1 keys | 4096 slots | 1 slaves.
192.168.4.51:6379 (0eb3b7aa...) -> 3 keys | 8192 slots | 1 slaves. 槽多了
192.168.4.52:6379 (a9cb8ccd...) -> 2 keys | 4096 slots | 1 slaves.
192.168.4.58:6379 (87cc1c12...) -> 0 keys | 0 slots | 0 slaves. 一个槽也没有了
[OK] 6 keys in 4 masters.
0.00 keys per slot on average.
[root@mgm57 ~]#
查看host58主机的id 然后删除主机 Host58
[root@mgm57 ~]# redis-trib.rb check 192.168.4.56:6379 | grep 192.168.4.58
M: 87cc1c128166e08a16cc294758611453bbc71437 192.168.4.58:6379
[root@mgm57 ~]#
[root@mgm57 ~]# redis-trib.rb del-node 192.168.4.56:6379 87cc1c128166e08a16cc294758611453bbc71437
>>> Removing node 87cc1c128166e08a16cc294758611453bbc71437 from cluster 192.168.4.56:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
[root@mgm57 ~]#
再次查看集群信息 (没有host58 主机了 )
[root@mgm57 ~]# redis-trib.rb info 192.168.4.56:6379
192.168.4.53:6379 (f2c1bdb7...) -> 1 keys | 4096 slots | 1 slaves.
192.168.4.51:6379 (0eb3b7aa...) -> 3 keys | 8192 slots | 1 slaves.
192.168.4.52:6379 (a9cb8ccd...) -> 2 keys | 4096 slots | 1 slaves.
[OK] 6 keys in 3 masters.
0.00 keys per slot on average.
[root@mgm57 ~]#
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~扩展知识
1) 平均分配当前所有主服务器的hash slots
[root@mgm57 ~]# redis-trib.rb info 192.168.4.56:6379 槽不平均
192.168.4.53:6379 (f2c1bdb7...) -> 1 keys | 4096 slots | 1 slaves.
192.168.4.51:6379 (0eb3b7aa...) -> 3 keys | 8192 slots | 1 slaves.
192.168.4.52:6379 (a9cb8ccd...) -> 2 keys | 4096 slots | 1 slaves.
[OK] 6 keys in 3 masters.
0.00 keys per slot on average.
[root@mgm57 ~]#
平均分配hash slots
[root@mgm57 ~]# redis-trib.rb rebalance 192.168.4.56:6379
再次查看平均了
[root@mgm57 ~]# redis-trib.rb info 192.168.4.56:6379
192.168.4.53:6379 (f2c1bdb7...) -> 2 keys | 5462 slots | 1 slaves.
192.168.4.51:6379 (0eb3b7aa...) -> 2 keys | 5461 slots | 1 slaves.
192.168.4.52:6379 (a9cb8ccd...) -> 2 keys | 5461 slots | 1 slaves.
[OK] 6 keys in 3 masters.
0.00 keys per slot on average.
首先 启动redis服务 清楚前世记忆 然后才能添加到集群
比如把移出的58主机再添加到集群里面
# 首先58
/etc/init.d/redis_6379 start
ss -tunlp | grep 6379
redis-trib.rb add-node 192.168.4.58:6379 192.168.4.52:6379
会说明连接不上redis服务,因为上面是有数据的
redis -cli -h 192.168.4.58 -p6379
cluster info # 发现还是ok 的
cluster reset # 回复原来没有加入集群的状态
keys * # 查看是否有数局
flushall # 清楚所有的数据
# 就可以再次添加到集群里面了
redis-trib.rb add-node 192.168.4.58:6379 192.168.4.52:6379 # 做主
redis-trib.rb rehard
2) 把移除的主机再次添加到集群里的步骤
第一步: 启动Redis服务并清除前世记忆(在Redis服务器本机操作)
第二步: 清空内存里的数据(在Redis服务器本机操作)
第三步: 在管理主机执行执行添加命令(在管理主机执行)
第四步: 查看是否添加成功(在管理主机执行)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~把移除host58再添加到集群里做master服务器
#58主机启动服务并清除前世记录
[root@host58 ~]# /etc/init.d/redis_6379 start
Starting Redis server...
[root@host58 ~]# netstat -utnlp | grep -i redis-server
tcp 0 0 192.168.4.58:6379 0.0.0.0:* LISTEN 4480/redis-server 1
tcp 0 0 192.168.4.58:16379 0.0.0.0:* LISTEN 4480/redis-server 1
[root@host58 ~]#
[root@host58 ~]# redis-cli -h 192.168.4.58 -p 6379
192.168.4.58:6379> cluster reset
OK
192.168.4.58:6379>
192.168.4.58:6379> keys *
(empty list or set)
192.168.4.58:6379>
#管理主机58 添加到集群里
[root@mgm57 ~]# redis-trib.rb add-node 192.168.4.58:6379 192.168.4.51:6351
#查看集群信息
[root@mgm57 ~]# redis-trib.rb info 192.168.4.51:6351 发现多了主服务器58
~~~~~~~~~~~~~~~~~~~~~~~~~~~~把 移除的59 再次添加到集群 做53主机的slave数据库服务器
命令格式
redis-trib.rb add-node --slave --master-id 主服务器的id 新服务器的ip:端口 集群中已有机器的Ip:端口
#启动53主机的redis服务并清除前世记录
]# /etc/init.d/redis_6379 start
]# redis-cli -h 192.168.4.59 -p 6379
> cluster reset
> exit
#在管理主机查看host53主机的id
[root@mgm57 ~]# redis-trib.rb check 192.168.4.51:6351 | grep 192.168.4.53
M: d9c9ef29c07ad740a05fa7aaa4d96ce25fa089b5 192.168.4.53:6353
[root@mgm57 ~]#
#添加59主机做主服务器53的 slave服务器
[root@mgm57 ~]# redis-trib.rb add-node --slave --master-id d9c9ef29c07ad740a05fa7aaa4d96ce25fa089b5 192.168.4.59:6379 192.168.4.51:6351
#查看集群信息
[root@mgm57 ~]# redis-trib.rb info 192.168.4.51:6351
192.168.4.51:6351 (4cf556bc...) -> 1 keys | 5461 slots | 1 slaves.
192.168.4.52:6352 (94cbe47c...) -> 3 keys | 5462 slots | 1 slaves.
192.168.4.53:6353 (d9c9ef29...) -> 2 keys | 5461 slots | 2 slaves. 53 有2台从服务器
[OK] 6 keys in 3 masters.
0.00 keys per slot on average.
[root@mgm57 ~]#
在是数据库服务器本机执行如下操作
#停止redis服务
#注释掉配置文件中的集群功能
#清空数据库目录
#启动服务
#连接服务查看不到集群信息 也没有数据
以数据库服务器host51为例演示:
[root@mgm57 ~]# redis-trib.rb info 192.168.4.56:6379
192.168.4.53:6379 (f2c1bdb7...) -> 2 keys | 5462 slots | 1 slaves.
192.168.4.51:6379 (0eb3b7aa...) -> 2 keys | 5461 slots | 2 slaves.
192.168.4.52:6379 (a9cb8ccd...) -> 2 keys | 5461 slots | 1 slaves.
[OK] 6 keys in 3 masters.
0.00 keys per slot on average.
[root@mgm57 ~]#
[root@host51 ~]# redis-cli -h 192.168.4.51 shutdown
[root@host51 ~]# vim /etc/redis/6379.conf
#cluster-enabled yes
#cluster-config-file nodes-6379.conf
#cluster-node-timeout 5000
[root@host51 ~]#
[root@host51 ~]# rm -rf /var/lib/redis/6379/*
[root@host51 ~]# /etc/init.d/redis_6379 start
Starting Redis server...
[root@host51 ~]#
[root@host51 ~]# netstat -utnalp |grep -i redis-server
tcp 0 0 192.168.4.51:6379 0.0.0.0:* LISTEN 9082/redis-server 1
[root@host51 ~]#
[root@host51 ~]# redis-cli -h 192.168.4.51 -p 6379
192.168.4.51:6379> keys *
(empty list or set)
192.168.4.51:6379> cluster info
ERR This instance has cluster support disabled 没有启用集群功能
192.168.4.51:6379>
#在管理主机查看集群信息看不到host51主机了
[root@mgm57 ~]# redis-trib.rb info 192.168.4.56:6379
192.168.4.54:6379 (bdba7786...) -> 2 keys | 5462 slots | 1 slaves.
192.168.4.52:6379 (a9cb8ccd...) -> 2 keys | 5461 slots | 1 slaves.
192.168.4.58:6379 (87cc1c12...) -> 2 keys | 5461 slots | 0 slaves.
[OK] 6 keys in 3 masters.
0.00 keys per slot on average.
[root@mgm57 ~]#
redis-cli -h `ifconfig eth0 | awk 'NR==2{print $2}'` shutdown sed -i '815c # cluster-enabled yes' /etc/redis/6379.conf && sed -i '829c # cluster-node-timeout 5000' /etc/redis/6379.conf && sed -i '823c # cluster-config-file nodes-6379.conf' /etc/redis/6379.conf && rm -rf /var/lib/redis/6379/* && /etc/init.d/redis_6379 start && netstat -utnalp |grep -i redis-server
for i in 51 52 53 54 55 56 58 59;do scp -r /linux-soft/4/redis/redis-4.0.8.tar.gz 192.168.4.$i:/root ; done
yum -y install gcc && tar xf redis-4.0.8.tar.gz && cd redis-4.0.8/ && make && make install
./utils/install_server.sh
ss -tunlp | grep 6379 && /etc/init.d/redis_6379 stop
sed -i '70c bind `ifconfig eth0 | awk 'NR==2{print $2}'`' /etc/redis/6379.conf && sed -i '815c cluster-enabled yes' /etc/redis/6379.conf && sed -i '829c cluster-node-timeout 5000' /etc/redis/6379.conf && sed -i '823c cluster-config-file nodes-6379.conf' /etc/redis/6379.conf
/etc/init.d/redis_6379 start && ss -tunlp | grep redis-server
# 集群控制器57
yum -y install ruby
scp /linux-soft/4/redis/redis-3.2.1.gem /linux-soft/4/redis/redis-4.0.8.tar.gz 192.168.4.57:/root # 脚本 和源码包
which gem || yum -y install rubygems
gem install redis-3.2.1.gem && tar xf redis-4.0.8.tar.gz && cd redis-4.0.8/ && ls src/*.rb && mkdir /root/bin && cp /root/redis-4.0.8/src/redis-trib.rb /root/bin
redis-trib.rb create --replicas 1 192.168.4.51:6379 192.168.4.52:6379 192.168.4.53:6379 192.168.4.54:6379 192.168.4.55:6379 192.168.4.56:6379
# 添加master主机58
redis-trib.rb add-node 192.168.4.58:6379 192.168.4.53:6379
redis-trib.rb reshard 192.168.4.53:6379 # 重新分配 hash槽
for i in 58 59;do scp -r /linux-soft/4/redis/redis-4.0.8.tar.gz 192.168.4.$i:/root && ssh 192.168.4.$i << EOF
yum -y install gcc
tar xf redis-4.0.8.tar.gz && cd redis-4.0.8/ && make && make install
./utils/install_server.sh << EOF
EOF
exit
EOF
done
与mysql主从同步功能都是一样的 都是实现数据自动备份的存储结构
redis主从复制 也分为主数据库服务器 和从数据库服务器2种角色
使用redis 主从副为至结构存储数据数据时候 ,也来连接主数据库服务器
redis主从辅助 结构分为“一主一从 一主多从 主从从
说明 默认redis服务运行后 就是master角色
主从复制结构 相关命令: 命令行制定主服务器信息 slaceof 主服务器IP 端口号
把配置保存到配置文件 config rewrite (永久生效)
查看复制信息命令 info replication
反客为主 (临时还原为主数据库服务器 slaveof no one
用来做服务器的机子是51 52 53
keys *
cluster info
info replication
一主一从
例子 把52配置为51的从数据库服务器
因为redis服务器运行后默认就是master角色数据库服务器 所以做主数据库服务器不需要做任何配置
配置数据库52
[root@localhost ~]# redis-cli -h 192.168.4.52
192.168.4.52:6379> SLAVEOF 192.168.4.51 6379
192.168.4.52:6379> CONFIG REWRITE
[root@localhost ~]# tail -1 /etc/redis/6379.conf
slaveof 192.168.4.51 6379
info replication 就可以查看是51的从数据库了
info replication # 51 上面就可以查看到冲服务器的资料
# 基于第一个实验 把数据库服务器53也配置为51的slave服务器
[root@localhost ~]# redis-cli -h 192.168.4.53 -p 6379
192.168.4.53:6379> info replication
192.168.4.53:6379> SLAVEOF 192.168.4.51 6379
192.168.4.53:6379> CONFIG REWRITE
[root@localhost ~]# tail -1 /etc/redis/6379.conf
slaveof 192.168.4.51 6379
192.168.4.53:6379> info replication
192.168.4.53:6379> slaveof on one # 变回master
此刻在主数据库服务器51 查看 就有2个从数据库的信息拉
192.168.4.51:6379> info replication
# 打开配置文件 找到slaveop 这一行 # 这是另外一种方法
slaveof 192.168.51 6379
# 然后重启服务
# 思考把主从结构中的从服务器永久恢复为独立的数据库服务器
基于上个实验一主多从 结构中的53永久回复独立的数据库服务器
主从从
要求 给一主一从机构中的52也配置为服务器,
192.168.4.53:6379> slaveof no one # 身份虽然是更换了,但是数据还是在的
192.168.4.53:6379> CONFIG REWRITE 或者 vim /etc/redis/6379.conf 将最后一行改为注释 但是需要重启服务才能实行
192.168.4.53:6379> SLAVEOF 192.168.4.52 6379
192.168.4.53:6379> CONFIG REWRITE
192.168.4.53:6379> info replication
# 主从结构中的 从服务器不允许执行写操作命令 只能查看
# 带验证的主从结构的配置 就是主数据库服务器的redis服务设置了连接密码 配置从服务器必须指定主服务器的连接密码 才能连接成功同步数据
练习
给 主从从结构中的主数据库服务器51设置redis的连接密码123456
config get requirepass # 查询配置文件中账号是否有密码
config set requirepass 123456 # 给账号输入密码
auth 123456 # 接下来需要输入密码才能够进行操作
config rewrite # 将配置输入配置文件 进行永久化
然后在从数据库服务器52主机 指定51主服务器的连接密码
没指定之前是同步了数据的
config set masterauth 123456 # 设置主服务器的密码
config rewrite # 写入配置文件
info replication # 能够连接上了说明是可以的了
redis主从+哨兵服务 51 52 53 56
实现redis集群的功能
redis的结构可以是一主多从 ,一主一从 主从从
使用主从从+哨兵服务 实现redis 集群的功能
要么全配置密码 ,要么全部都不配置连接密码
哨兵服务的工作过程: 服务运行过程中监视主从结构中的主数据库服务器 主坏掉后会把对应的从服务器升级为主服务器,坏调的主机回复后 会自动做当前主服务器的从主机
说明:如果主从结构中的主服务器上的redis服务设置的连接密码 ,那么其他的服务器都要设置连接密码 并且连接密码需要一样
其次 当坏掉的主服务器加入集群时候需要人为设置连接当前主服务器的密码
# 由于上面实验51是设置了连接密码的,所以下面都redis都是需要设置密码的
# 给52的主机redis服务设置连接密码
config set requirepass 123456
auth 123456 # 设置了密码 的时候从是连接不上的,因为刚设置了密码,需要在从数据库服务器上面设置主的服务器密码,
config rewrite
# 配置53主机 指定连接主服务器的连接密码 给自己redis服务设置连接密码
config set masterauth 123456 # 指定主的服务器的连接密码
config set requirepass 123456
auth 123456
config rewrite
# 配置哨兵服务器56 需要有redis的安装软件包
rm -rf redis-4.0.8 # 删除以前解压的源码
#安装redis软件(不需要做初始化配置)因为不需要使用到redis的存储功能
yum -y install gcc && tar xf redis-4.0.8.tar.gz && cd redis-4.0.8/ && make && make install
# 创建并编辑哨兵服务的主配置文件
vim /etc/sentinel.conf
bind 192.168.4.56 # 哨兵的IP
port 26379 # 端口
sentinel monitor redis_server 192.168.4.51 6379 1
sentinel auth-pass redis-server 123456
-- redis_server 给redis 起的别名
-- 192.168.4.51 6379 redis的主IP和端口
-- 1 哨兵的台数
-- sentinel monitor 监视的主机
-- sentinel auth-pass 监视主机的服务器连接密码
# 哨兵启动的时候 就去监视主从结构当前的主,如果发现主宕机了,会把从升级为主服务器
# 启动哨兵服务
redis-sentinel /etc/sentinel.conf # 会有启动信息输出,会占用终端显示
nohup redis-sentinel /etc/sentinel.conf & # 可以将它放到后台运行
# 测试配置
# 没有停止51的redis服务之前,查看52主机的复制信息 52是slave角色
redis-cli -h 192.168.4.52 -p 6379 -P 123456
192.168.4.52:6379> INfo replication # 查看是slave角色
192.168.4.51:6379> info replication # 查看是master角色
#停止51的服务查看52的角色
redis-cli -h 192.168.4.51 -p 6379 -P 123456 shutdown
192.168.4.52:6379> info replication
grep -i "sentinel monitor" /etc/sentinel.conf # 查看56 上面的配置文件
# sentinel monitor redis_server 192.168.4.52 6379 1
cat /etc/sentinel.conf # 就会发现是里面的内容已经是变多了的
# 启动51 的redis服务查看复制信息 会成为52的从服务器 ,但连接状态是down 需要指定连接密码
/etc/init.d/redis_6379 start
ss -tunlp | grep redis
192.168.4.51:6379> info replication # 发现是down 状态 原因是没有连接主服务器的密码
192.168.4.51:6379> config set masterauth 123456
192.168.4.51:6379> auth 123456
192.168.4.51:6379> config rewrite
192.168.4.51:6379> info replication # 再次查看就会发现是up状态了,这样就是已经是实现了哨兵模式了的
总结:
redis服务是先把客户端的数据保存在内存里面的
服务正常停止的情况下 会自动把内存里的数据复制到硬盘里
在服务运行过程中会把每一段时间 自动把内存里的数据复制到硬盘里面
RDB:(默认使用的方法) 指的就是数据库目录下面的/demp.rdb 文件里面
按照配置文件设置的存盘频率 把内存里的数据 复制到硬盘里用demp.rdb 保存
AOF(默认没有启用) 类似于mysql数据库服务的binlog日志文件
以追加的方式记录用户在redis服务器上执行的写操作命令
RDB有个致命的弱点:意外宕机贵丢失某次的存盘频率的所有数据
AOF记录命令的方式
appendfsync always 703 实时记录 影响CPU的性能
appendfsync everysec 704 每秒记录一次
appendfsync no 705 只是把命令记录到aof文件里面不把命令产生
修复有问题的aof文件 当aof文件会导致服务不能启动
ls /var/lib/redis/6379/ # 可以通过备份dump.rdb此文件以达到数据备份的效果
redis-cli -h 192.168.4.53 -p 6379
192.168.4.53:6379> SAVE # 将数据存盘
exit
cp /var/lib/redis/6379/dump.rdb /opt/ # 备份数据
192.168.4.53:6379> FLUSHALL # 删除数据
redis-cli -h 192.168.4.53 -p 6379 shutdown # 停止服务
ls /var/lib/redis/6379/ #但是文件还是有的,但是没有数据
rm -rf /var/lib/redis/6379/dump.rdb # 删除原有的目录
cp /opt/dump.rdb /var/lib/redis/6379/ # 将备份文件拷贝回来
/etc/init.d/redis_6379 start
redis-cli -h 192.168.4.53 -p 6379 # 登录上去还是可以查看数据的
# 验证RDB方式的存盘频率
第一个是 查看默认
vim /etc/redis/6379.conf
save 900 1 # 219行
save 120 10 # 修改为2分钟内存10个变量 就会触发存盘
save 60 10000
redis-cli -h 192.168.4.53 -p 6379 shutdown
/etc/init.d/redis_6379 start
rm -rf /var/lib/redis/6379/dump.rdb # 为了实现到了存盘频率并且就可以创建文件
redis-cli -h 192.168.4.53 -p 6379 # 在里面创建十个以上变量并且到达指定时间就可以自动存盘了
vim /etc/redis/6379.conf
appendonly yes # 674行
192.168.4.53:6379> CONFIG SET appendonly yes # 设置为yes
192.168.4.53:6379> CONFIG REWRITE # 永久生效
ls /var/lib/redis/6379/appendonly.aof # 就会发现有这个文件了,
192.168.4.53:6379> MSET name bob age 10 add ddd # 再存储点数据
cp /var/lib/redis/6379/appendonly.aof /opt/
redis-cli -h 192.168.4.53 -p 6379 shutdown
rm -rf /var/lib/redis/6379/*
cp /opt/appendonly.aof /var/lib/redis/6379/
/etc/init.d/redis_6379 start
redis-cli -h 192.168.4.53 -p 6379
192.168.4.53:6379> KEYS *
# 先查看服务的日志文件 找报错信息
grep -i 'logfile' /etc/redis/6379.conf
tarl 1 /var/log/redis_6379.log
redis-check-aof --fix /var/lib/redis/6379/appendonly.aof
可以在任何一台redis数据库服务器上面做都可以
注意;主从结构中的从是默认不支持写操作的
# 53
slaveof no one
CONFIG REWRITE
# /etc/redis/6379.conf 最后一样的配置改为注释 redis-cli -h 192.168.4.53 -p 6379 shutdown /etc/init.d/redis_6379 start 如果哨兵模式没有关闭的话,会一直会成为从服务器
set age 19 ex 20 # 设置变量并设置时间
ttl age # 查看变量还剩多少的存活时间
set name bob px 20 # 这个是设置毫秒
set x 201 xx # 覆盖存储
set x 301 nx # 不覆盖存储
get x # 值还是201
set zfc ABCDEF
GETRANGE zfc 0 2 # 获取变量的指定范围值 从0开始
GETRANGE zfc -2 -1
STRLEN zfc # 统计变量字符串的个数
APPEND zfc "HIJK" # 给字符串最加HIJK 返回当前字符串的长度 当没有该变量的时候会创建该变量并且赋值
set i 1
DECR i # 自减1 本来是字符串类型,但是如果是数值的字符串,会自转换为数值类型,再减1
get i
DECRBY i 2 # 定义自减的长度
INCR i # 自加1
INCRBY i 2 # 定义自增的长度 但是不能加小数的
INCRBYFLOAT i 2.5 # 可以加小数的指定命令
setbit 使用二进制数给变量赋值 目的是节省内存存储空间 计算机的进制
setbit 变量名 第几位 二进制数
二进制数 只能是0或1
计算机的进制单位 :G M K byts 位
1G = 1024M ;1M = 1024k ; 1k = 1024byts 1byts = 8位
# 把1k换算成 二进制是多少位 1024×8
使用变量login 存储1年的游戏账号登录状态
就是当前学过的数组
数组就是让一个变量存储多个值 多个值之间使用下标区分
后进先出 先出后进
lpush teacher nb wk zzg nfx plj lx dmy # 最后添加的在最前面
LRANGE teacher 0 -1
KEYS *
TYPE teacher #是列表类型
LLEN teacher # 统计多少个值
LINDEX teacher 2 # 将下标为2的值输出来
lset teacher 3 panglijing # 修改对用相应的值
lpop teacher # 将列表中的第一个元素弹出
RPUSH teacher A B C # 向已有的的列表最加元素,末尾
RPOP teacher # 弹出列表中最后的一个元素
LREM teacher 1 nb # 移出元素
也叫做hash类型
{name :”plj”,age : 19 } 类似与python里面的字典
一个变量可以存储多列 每列对应一个值
HSET xng shell 60 # 创建hash类型 ,并
KEYS *
type xng # 查看是hash类型
HGETALL xng # 把hash类型里面的值都显示出来
hmset lzm addr bj
HMSET lzm mail [email protected] tel 101 age 58 # 一次存储多个变量
hget lzm tel # 只要变量中的某一项元素的值
HDEL xng shell db1 db2 # 一次删除多个元素
HKEYS xng # 查看hash类型中的键
ZRANGE plj 0 -1 withscores # 将对应的值也显示出来
集合数据类型分为2中
有序集合
ZADD plj 10 game # 值是可以重复的,但是变量名是不可重复的
type plj # 查看出来是zset有序集合类型
ZRANGE plj 0 -1 # 显示所有变量名
ZSCORE plj game # 显示变量名对应的值
ZRANGEBYSCORE plj 10 30 # 显示对应10到30之间的变量名
ZCARD plj # 查看有多少中变量名
ZREM plj it cd # 删除集合对应的变量名
set无序集合 : 没有下标的列表类型 但值是唯一的
# 使用一个变量存储爱好
SADD plj sleep eat mony game
type plj # 查看是set类型
SMEMBERS plj # 查看所有值,是没有顺序的
SREM plj mony # 删除集合里面mony的值
SADD xng sleep game it
SINTER plj xng # 两个集合的交集
SUNION plj xng # 两个集合的 ,重复的只显示一边
SDIFF plj xng # 比较两个集合的不同之处
SCARD plj # 统计集合里面的元素
SRANDMEMBER plj 1 # 随即输出一个爱好
回顾昨天学习的知识
1。 编写mysql多实例的配置文件 有2部分要自己编写 管理多实例服务的运行参数配置[mysqld_multi] 多实例的配置[mysqld1 ]…就是只要服务器硬件好就可以运行很多个数据库进程 启动实例的 启动 停止 连接
昨天的只是点回顾 mysql高可用集群
使用mha软件+mysql主从同步 部署mysql高可用集群
具体配置过程: 主从同步必须配置 免密登录配置 所有数据库服务器都必须 启用binlog日志 用户授权 启用半同步复制功能 禁止自动删除中继日志文件 配置管理主机 安装软件 创建主配置文件并编辑 创建故障切换脚本 配置数据库服务器 : 创建监控用户 把故障切换脚本中制定的vip地址部署在当前主从结构中的主数据库服务器上 安装mha_node软件 测试配置: 测试ssh免密配置 测试主从同步配置 启动管理 注意: 要让管理服务 继续监视新下主数据库服务器 要认为的启动管理服务 测试配置 把宕机的数据库服务器得人为添加到集群里面 并要人为完成宕机期间的数据同步
回顾昨天的只是
PXC集群 pxc软件介绍 部署PXC 安装PXC软件 修改配置文件 mysqld。cnf wsreo.cnf 初始化集权 启动另外两台服务器的mysqld服务 查看集群信息 测试集群 MySQL存储引擎 什么是存储引擎 mysql服务的体系结构 存储引擎的管理 查看修改数据库服务使用的存储引擎 查看修改表使用的存储引擎 建表时候指定表使用的存储引擎管理 常用存储引擎的特点 myisam innodb 专业术语 什么是事务 什么是是事务回滚 表级锁 行级锁 读锁 写锁 晚自习完成的学习任务:数据库服务软件的类型RDBMS NoSQL 对应的服务软件有那些 关系型数据库有哪些 非关系型数据库有那些 他们之间的各自特点是什么 这个查看工作中需要那些数据库 Redis软件介绍 部署Redis服务器 192.168.4.50 网站服务器 192.168.4.51 LNP 今天要完成的任务是LNP+Redis 和部署Redis集群 (实现的需求 是把网站的数据存储在50主机的内存)
是第一阶段到第四阶段所学的知识
LVM NFS tomcat 格式化 挂载
数据迁移
数据服务的负载均衡+高可用集群
部署缓存服务实现网站(把网站的数据存放到内存里)
PXC keepalived haproxy redis集群
最终使用要完成的效果
给公司万站部署2太数据存储集群机构:
1套是硬盘存储集群架构 ,并要使用服务到高可用,数据的自动备份和服务的负载均衡
1套是内存存储集群架构,也要实现服务的高可用,数据的自动备份和服务的负载均衡
内存存储架构用来存储网站热点数据 和 可再生的数据 ,
要完成的实验结果:
一 把网站的数据存储在mysql数据读写分离结构里面
1.1 把数据服务器额外添加两块LV 用来存储数据服务器的数据 (存储空间可以动态扩展)
1.2 把mysql服务的数据存储在逻辑卷里面
1.3 配置mysql主从同步
1.3.1 配置主数据库服务器mysql11
1.3.2 配置从数据库服务器mysql22
1.3.3
二 把网站的网页文件存储在NFS共享服务器里面
三 配置网站服务器
四 测试配置
4.1 测试tomcat
4.2 测试nfs配置
#在30编写连接mysqld服务存储数据的脚本
4.3
案例1:配置逻辑卷
(把数据库服务器的数据存储到逻辑卷(LV)里,目的是可以动态扩展数据库服务器
硬盘的存储空间)
具体步骤如下:
1) 给2台数据库服务器mysql11 和 mysql22 分别添加2块5G的硬盘
2) 划分物理分区 (/dev/vdb1 /dev/vdc1)
3) 创建物理卷
4) 创建卷组vg0
5) 创建逻辑卷lv0
6) 格式化lv0 (文件系统类型是xfs)
操作命令如下:
4 systemctl stop mysqld
5 yum -y install lvm2
6 lsblk
7 pvcreate /dev/vdb /dev/vdc
8 vgcreate vg0 /dev/vdb /dev/vdc
9 vgs
10 lvcreate -n lv0 -L 5.99g vg0
11 lvscan
12 mkfs.xfs /dev/vg0/lv0
13 blkid /dev/vg0/lv0
案例2:配置数据库服务器
具体步骤如下:(2台数据库服务器主机分别做如下操作)
1) 安装 mysql服务软件
2)开机挂载逻辑卷lv0 到数据库目录下
3)启动mysql服务并设置开机启动
4) 查看初始密码并使用初始密码登录
5) 修改数据库管理员密码 并断开连接
6) 使用修改后的密码登录
]# rm -rf /var/lib/mysql/*
]# vim /etc/fstab
/dev/vg0/lv0 /var/lib/mysql xfs defaults 0 0
:wq
]# mount -a
]# mount | grep "/var/lib/mysql"
]# systemctl start mysqld
]# grep password /var/log/mysqld.log | tail -1
]# mysqladmin -uroot -p'Tih:Zehtr57s' password "123qqq...A"
]# mysql -uroot -p123qqq...A
案例3:配置主从同步:(读写分离存储数据时 能让用户存储的数据和查看的是一致)
1) 配置主数据库服务器 mysql11(192.168.4.11)
具体操作如下:
1) 启用binlog日志文件
2) 用户授权
3) 查看正在使用的binlog日志名和偏移量 (准备从服务器使用)
mysql11]# vim /etc/my.cnf
[mysqld]
server_id=11
log_bin=master11
:wq
mysql11]# systemctl restart mysqld
mysql11]# mysql -uroot -p123qqq...A
mysql> grant replication slave on *.* to repluser@"%" identified by "123qqq...A";
mysql>
mysql> show master status;
+-----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------+----------+--------------+------------------+-------------------+
| master11.000001 | 1026 | | | |
+-----------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
2) 配置从数据库服务器 mysql11(192.168.4.22)
具体操作如下:
1)指定server_id (修改配置设置server_id 所以要重启服务)
2)管理员登录数据库服务,指定主服务器信息,指定的信息
包括(ip 用户 密码 日志名 偏移量)
3)启动slave进程
4)查看IO线程和SQL线程的状态(都是Yes 就配置对了)
mysql22]# vim /etc/my.cnf
[mysqld]
server_id=22
:wq
mysql11]# systemctl restart mysqld
mysql11]# mysql -uroot -p123qqq...A
mysql> change master to master_host="192.168.4.11" , master_user="repluser" , master_password="123qqq...A",
master_log_file="master11.000001" , master_log_pos=441;
mysql> start slave;
mysql> show slave status \G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
案例4:配置读写分离服务: (ip 地址 是 192.168.4.77 主机名maxscal77)
(把客户端连接自己后的查询请求给slave 数据库服务器, 把写请求master数据库服务器)
具体配置步骤如下:
1)安装软件 yum -y install maxscale-2.1.2-1.rhel.7.x86_64.rpm
2)修改配置文件
vim /etc/maxscale.cnf
[maxscale]
threads=auto
[server1]
type=server
address=192.168.4.11
port=3306
protocol=MySQLBackend
[server2]
type=server
address=192.168.4.22
port=3306
protocol=MySQLBackend
[MySQL Monitor]
type=monitor
module=mysqlmon
servers=server1,server2
user=mysqla
passwd=123qqq...A
monitor_interval=10000
#[Read-Only Service]
#type=service
#router=readconnroute
#servers=server1
#user=myuser
#passwd=mypwd
#router_options=slave
[Read-Write Service]
type=service
router=readwritesplit
servers=server1,server2
user=mysqlb
passwd=123qqq...A
max_slave_connections=100%
[MaxAdmin Service]
type=service
router=cli
#[Read-Only Listener]
#type=listener
#service=Read-Only Service
#protocol=MySQLClient
#port=4008
[Read-Write Listener]
type=listener
service=Read-Write Service
protocol=MySQLClient
port=4006
[MaxAdmin Listener]
type=listener
service=MaxAdmin Service
protocol=maxscaled
socket=default
port=4016
:wq
3)配置数据库服务器 (只需要在主数据库服务器mysql11 用户 从服务器会自动同步用户)
replication slave, 查看主从角色
replication client 查看mysql数据库服务运行状态
[root@mysql11 ~]# mysql -uroot -p123qqq...A
mysql> grant replication slave , replication client on *.* to mysqla@"%" identified by "123qqq...A"; 监控用户
mysql> grant select on *.* to mysqlb@"%" identified by "123qqq...A"; 路由用户
在从数据库服务器查看是否同步授权用户名
[root@mysql22 ~]# mysql -uroot -p123qqq...A
mysql> select user from mysql.user where user="mysqla";
mysql> select user from mysql.user where user="mysqlb";
4) 启动maxscale服务 (在maxscale77 主机启动服务)
[root@maxscale77 ~]# maxscale /etc/maxscale.cnf
5) 查看maxscale服务状态
[root@maxscale77 ~]# netstat -utnlp | grep 4016
tcp6 0 0 :::4016 :::* LISTEN 1125/maxscale
[root@maxscale77 ~]# netstat -utnlp | grep 4006
tcp6 0 0 :::4006 :::* LISTEN 1125/maxscale
[root@maxscale77 ~]#
6)查看监控信息(在maxscale77 访问自己的管理服务,查看监控信息)
[root@maxscale77 ~]# maxadmin -uadmin -pmariadb -P4016
MaxScale> list servers
Servers.
-------------------+-----------------+-------+-------------+--------------------
Server | Address | Port | Connections | Status
-------------------+-----------------+-------+-------------+--------------------
server1 | 192.168.4.11 | 3306 | 0 | Master, Running
server2 | 192.168.4.22 | 3306 | 0 | Slave, Running
-------------------+-----------------+-------+-------------+--------------------
MaxScale> exit
[root@maxscale77 ~]#
案例5:准备NFS服务存储磁盘 (IP 192.168.4.30主机提供nfs服务 ,存储网站web33的网页文件)
步骤一 :
1)添加1块3G 磁盘
2) 磁盘分区 (分一个区 /dev/vdb1)
3) 格式化
[root@NFS30 ~]# lsblk 分区前查看
[root@NFS30 ~]# fdisk /dev/vdb -> n -> p -> 三个回车-> w
[root@NFS30 ~]# lsblk 分区后查看
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 30G 0 disk
└─vda1 253:1 0 30G 0 part /
vdb 253:16 0 3G 0 disk
└─vdb1 253:17 0 3G 0 part
[root@NFS30 ~]# mkfs.xfs /dev/vdb1
步骤二:挂载磁盘
[root@NFS30 ~]# mkdir /sitedir
[root@NFS30 ~]# vim /etc/fstab
/dev/vdb1 /sitedir xfs defaults 0 0
:wq
[root@NFS30 ~]# mount -a
[root@NFS30 ~]# mount | grep -i "/sitedir"
/dev/vdb1 on /sitedir type xfs (rw,relatime,attr2,inode64,noquota)
[root@NFS30 ~]#
案例6:配置NFS服务 (192.168.4.30 把目录共享给客户端 )
1)安装软件
2)修改配置文件
3) 启动服务 (先启动rpcbind服务 再启动nfs服务)
4)查看共享信息
[root@NFS30 ~]# yum -y install nfs-utils rpcbind
[root@NFS30 ~]# vim /etc/exports
/sitedir *(rw)
:wq
[root@NFS30 ~]# chmod o+w /sitedir/
[root@NFS30 ~]# systemctl restart rpcbind
[root@NFS30 ~]# systemctl enable rpcbind
[root@NFS30 ~]# systemctl restart nfs
[root@NFS30 ~]# systemctl enable nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
[root@NFS30 ~]# showmount -e localhost
Export list for localhost:
/sitedir *
[root@NFS30 ~]#
案例7:配置网站服务192.168.4.33 主机名web33
1)安装软件apache-tomcat-8.0.30.tar.gz (使用tomcatr软件提高的网站服务)
2)挂载nfs服务的共享目录(把网站的网页存放的nfs30主机里)
3)查看挂载
4) 启动tomcat服务
5) 查看tomcat服务运行信息
yum -y install java-1.8.0-openjdk
tar -xf apache-tomcat-8.0.30.tar.gz
mv apache-tomcat-8.0.30 /usr/local/tomcat
rm -rf /usr/local/tomcat/webapps/ROOT/*
which showmount || yum -y install nfs-utils
[root@web33 ~]# showmount -e 192.168.4.30
Export list for 192.168.4.30:
/sitedir *
[root@web33 ~]#
[root@web33 ~]# vim /etc/fstab
192.168.4.30:/sitedir /usr/local/tomcat/webapps/ROOT nfs defaults 0 0
:wq
[root@web33 ~]# mount -a
[root@web33 ~]# df -h
文件系统 容量 已用 可用 已用% 挂载点
/dev/vda1 30G 1.4G 29G 5% /
devtmpfs 697M 0 697M 0% /dev
tmpfs 707M 0 707M 0% /dev/shm
tmpfs 707M 8.5M 699M 2% /run
tmpfs 707M 0 707M 0% /sys/fs/cgroup
tmpfs 142M 0 142M 0% /run/user/0
192.168.4.30:/sitedir 3.0G 32M 3.0G 2% /usr/local/tomcat/webapps/ROOT 已经挂载
[root@web33 ~]#
[root@web33 ~]# /usr/local/tomcat/bin/startup.sh ^C
[root@web33 ~]#
[root@web33 ~]# netstat -utnlp | grep :8080
tcp6 0 0 :::8080 :::* LISTEN 1371/java
[root@web33 ~]#
案例8:测试配置
一 、测试NFS服务
1)在nfs服务器创建网页 test.html
[root@NFS30 ~]# vim /sitedir/test.html
web test page
:wq
2)在客户端访问网站服务(在任意一台主机上访问web33 网页)
]# curl http://192.168.4.33:8080/test.html
web test page
二、测试MySQL服务
2.1、 在主数据库服务器mysql11 做如下配置
[root@mysql11 ~]# mysql -uroot -p123qqq...A
create database gamedb;
create table gamedb.user ( name char(10) , password char(6));
grant select, insert on gamedb.* to yaya@"%" identified by "123qqq...A";
2.2、在从服务器 检查是否同步库表 和 授权用户
[root@mysql22 ~]# mysql -uroot -p123qqq...A -e 'desc gamedb.user'
[root@mysql22 ~]# mysql -uroot -p123qqq...A -e 'select user from mysql.user where user="yaya"'
2.3 在网站服务器命令行 连接 maxscale77
web33]# yum -y install mariadb
web33]# mysql -h192.168.4.77 -P4006 -uyaya -p123qqq...A
mysql>exit ;
三、测试Tomcat连接MySQL服务(在网页目录下编写网站脚本文件 访问数据库服务)
1)在网站服务器做如下配置
[root@web33 ~]# yum -y install mysql-connector-java
[root@web33 ~]# cp /usr/share/java/mysql-connector-java.jar /usr/local/tomcat/lib/
[root@web33 ~]# /usr/local/tomcat/bin/shutdown.sh
[root@web33 ~]# /usr/local/tomcat/bin/startup.sh
1)编写网站脚本(在nfs服务共享目录编写网页文件)
[root@nfs30 ~]# vim /sitedir/linkdb.jsp
<%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
<%@ page import="java.naming.*" %>
<%@ page import="java.sql.*" %>
<%
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://192.168.4.77:4006","yaya","123qqq...A");
Statement state=con.createStatement();
String sql="insert into gamedb.user values('bbb','654321')";
state.executeUpdate(sql);
%>
data save ok
2)在浏览器地址栏里输入网站访问 或 命令行连接访问 都可以
[root@NFS30 ~]# curl http://192.168.4.33:8080/linkdb.jsp
data save ok
3)在据库服务器查看数据 (可以查看到linkdb.jsp 脚本里 Insert into 命令添加的记录 )
[root@mysql11 ~]# mysql -uroot -p123qqq...A -e 'select * from gamedb.user'
[root@mysql22 ~]# mysql -uroot -p123qqq...A -e 'select * from gamedb.user'
改变网站运行平台LNP(nginx) + MySQL
把存储在读写分离存储结构里的数据辅助到mysql高可用集群里面(在线复制)
部署内存存储服务器,让网站把经常被访问的数据存储在内存里,可以加快网站服务的处理速度
案例1:升级网站运行平台
步骤一 清除当前配置 (删除web33主机的tomcat服务的配置)
1)停止网站服务
2)卸载共享存储
[root@web33 ~]# /usr/local/tomcat/bin/shutdown.sh
[root@web33 ~]# umount /usr/local/tomcat/webapps/ROOT //卸载当前挂载
[root@web33 ~]# vim /etc/fstab //清除开机挂载
#192.168.4.30:/sitedir /usr/local/tomcat/webapps/ROOT nfs defaults 0 0
:wq
步骤二:部署LNP
1)安装软件
2)挂载共享存储(把NFS30的共享目录/sitedir 挂载到nginx的网页目录下)
3)启动服务
要先修改配置文件把访问php页面的请求给本机的9000端口处理
再启动nginx 服务
[root@web33 ~]# yum -y install gcc zlib-devel pcre-devel php php-devel php-mysql php-fpm
[root@web33 ~]# tar -xf nginx-1.12.2.tar.gz //解压
[root@web33 ~]# cd nginx-1.12.2 //进源码目录
[root@web33 nginx-1.12.2]# ./configure //配置
[root@web33 nginx-1.12.2]# make && make install
[root@web33 ~]# vim /etc/fstab //开机挂载
192.168.4.30:/sitedir /usr/local/nginx/html nfs defaults 0 0
:wq
[root@web33 ~]# mount -a //挂载设备
[root@web33 ~]# vim +65 /usr/local/nginx/conf/nginx.conf //修改主配置文件
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
:wq
[root@web33 ~]# /usr/local/nginx/sbin/nginx //启动服务
[root@web33 ~]# systemctl start php-fpm
步骤三:测试配置
1)编写PHP脚本 (在NFS30的共享目录编写连接MySQL服务的php脚本)
[root@NFS30 ~]# vim /sitedir/linkdb2.php
<?php
$conn=mysql_connect("192.168.4.11","yaya","123qqq...A");
mysql_select_db("gamedb");
$sql = 'insert into user (name,password) values ("PANGLJ","666888")';
mysql_query($sql);
mysql_close();
echo "save data ok";
?>
:wq
2)访问脚本 (在任意1台主机访问web33主机的网站服务 执行linkdb2.php脚本)
[root@NFS30 ~]# curl http://192.168.4.33/linkdb2.php
save data ok
3)查看数据 (在数据库服务器mysql11 和 mysql22 本机查看数据,
能看到php脚本存储的数据就成功里)
[root@mysql22 ~]# mysql -uroot -p123qqq...A -e 'select * from gamedb.user';
[root@mysql11~]# mysql -uroot -p123qqq...A -e 'select * from gamedb.user';
休息到 16:05
案例2:部署内存存储服务(部署Redis集群 ,使用内存存储网站的数据)
步骤一:部署redis服务器(6台都要配置)
具体操作步骤: 安装redis软件 、 初始化配置 、停止redis服务、启用集群功能、 启动redis 服务
配置Host51 52 53 54 55 56主机
[root@redisA ~]# rpm -q gcc || yum -y install gcc //安装编译工具
[root@redisA ~]# tar -xf redis-4.0.8.tar.gz //解压
[root@redisA ~]# cd redis-4.0.8/ //进源码目录
[root@redisA ~]# make
[root@redisA redis-4.0.8]# make install //安装软件
[root@redisA redis-4.0.8]# ./utils/install_server.sh //初始化配置 遇到提示敲回车
[root@redisA redis-4.0.8]# /etc/init.d/redis_6379 stop //停止服务
[root@redisA redis-4.0.8]# vim /etc/redis/6379.conf //修改配置文件,启用集群配置
70 bind 192.168.4.51
93 port 6379
815 cluster-enabled yes
823 cluster-config-file nodes-6379.conf
829 cluster-node-timeout 5000
[root@redisA redis-4.0.8]# /etc/init.d/redis_6379 start //启动服务
[root@redisA redis-4.0.8]# netstat -utnlp | grep redis-server //查看端口
tcp 0 0 192.168.4.51:6379 0.0.0.0:* LISTEN 29720/redis-server //redis服务端口
tcp 0 0 192.168.4.51:16379 0.0.0.0:* LISTEN 29720/redis-server //集群端口
步骤二:创建redis集群
1)配置管理主机: 安装gem软件 创建ruby脚本
[root@mgm ~]# yum -y install ruby rubygems //安装依赖
[root@mgm ~]# gem install redis-3.2.1.gem //安装依赖软件gem程序
[root@mgm ~]# mkdir /root/bin
[root@mgm ~]# tar -xf redis-4.0.8.tar.gz
[root@mgm ~]# cp redis-4.0.8/src/redis-trib.rb /root/bin/ //拷贝脚本
[root@mgm ~]#
[root@mgm ~]# chmod +x /root/bin/redis-trib.rb //确保脚本有执行权限
2)创建集群
mgm~]#redis-trib.rb create --replicas 1 \
192.168.4.51:6379 192.168.4.52:6379 192.168.4.53:6379 \
192.168.4.54:6379 192.168.4.55:6379 192.168.4.56:6379
......
Can I set the above configuration? (type 'yes' to accept): yes 同意
....
....
>>> Check slots coverage...
[OK] All 16384 slots covered. 集群创建成功的提示信息
3)查看集群信息
[root@mgm ~]# redis-trib.rb info 192.168.4.51:6379
192.168.4.51:6379 (8221af1a...) -> 0 keys | 5461 slots | 1 slaves.
192.168.4.52:6379 (fc08343f...) -> 0 keys | 5462 slots | 1 slaves.
192.168.4.53:6379 (94213188...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
步骤三:配置网站服务器 (web33)
(让网站的php脚本可以连接redis 集群中任意服务器查询和存储数据)
1) 安装连接redis集群的redis.so模块
2)修改php的配置文件 php.ini 加载模块
3) 查看支持的模块
[root@web33 ~ ]# yum -y install php-devel //安装依赖
[root@web33 ~]# tar -xf redis-cluster-4.3.0.tgz //解压
[root@web33 ~]# cd redis-4.3.0/ //进入源码目录
[root@web33 redis-4.3.0]# phpize //创建configure命令及配置信息文件/usr/bin/php-config
Configuring for:
PHP Api Version: 20100412
Zend Module Api No: 20100525
Zend Extension Api No: 220100525
[root@web33 redis-4.3.0]#
[root@web33 redis-4.3.0]# ./configure --with-php-config=/usr/bin/php-config
[root@web33 redis-4.3.0]# make //编译
[root@web33 redis-4.3.0]# make install //安装
Installing shared extensions: /usr/lib64/php/modules/ //提示模块安装目录
[root@web33 redis-4.3.0]# vim /etc/php.ini
728 extension_dir = "/usr/lib64/php/modules/" //模块目录
730 extension = "redis.so" //模块名
:wq
[root@web33 redis-4.3.0]# systemctl restart php-fpm //重启php-fpm服务
[root@web33 redis-4.3.0]# php -m | grep redis
redis
[root@web33 redis-4.3.0]#
步骤四:测试配置
休息到 17:05
1)在存储服务器共享目录下,创建连接集群PHP脚本
(在脚本连接集群后执行存储数据名和查询数据的命令)
[root@NFS30 ~]# vim /sitedir/set_data.php 存储数据的PHP脚本
<?php
$redis_list = ['192.168.4.51:6379','192.168.4.52:6379','192.168.4.53:6379','192.168.4.54:6379','192.168.4.55:6379','192.168.4.56:6379']; //定义redis服务器列表
$client = new RedisCluster(NUll,$redis_list); //定义连接redis服务命令
$client->set("i","tarenaA "); //存储数据 变量名 i
$client->set("j","tarenaB "); //存储数据 变量名 j
$client->set("k","tarenaC "); //存储数据 变量名 k
echo "save ok";
?>
:wq
[root@NFS30 ~]#
[root@NFS30 ~]#
[root@NFS30 ~]# vim /sitedir/get_data.php 查看数据的PHP脚本
<?php
$redis_list = ['192.168.4.51:6379','192.168.4.52:6379','192.168.4.53:6379','192.168.4.54:6379','192.168.4.55:6379','192.168.4.56:6379']; //定义redis服务器列表
$client = new RedisCluster(NUll,$redis_list); //定义连接redis服务命令
echo $client->get("i"); //获取变量i 的数据
echo $client->get("j"); //获取变量j 的数据
echo $client->get("k"); //获取变量k 的数据
echo "get ok";
?>
:wq
[root@NFS30 ~]#
[root@NFS30 ~]# vim /sitedir/test3.php 存储+查询的PHP脚本
<?php
$redis_list = ['192.168.4.51:6379','192.168.4.52:6379','192.168.4.53:6379','192.168.4.54:6379','192.168.4.55:6379','192.168.4.56:6379'];
$client = new RedisCluster(NUll,$redis_list);
$client->set("name","panglijing"); //存数据
echo $client->get("name"); //取数据
?>
:wq
[root@NFS30 ~]#
2)访问网站执行脚本(在任意主机访问网站服务器都可以)
[root@NFS30 ~]# curl http://192.168.4.33/set_data.php
save ok[root@NFS30 ~]#
[root@NFS30 ~]#
[root@NFS30 ~]#
[root@NFS30 ~]# curl http://192.168.4.33/get_data.php
tarenaA tarenaB tarenaC get ok
[root@NFS30 ~]#
[root@NFS30 ~]# curl http://192.168.4.33/test3.php
panglijing[root@NFS30 ~]#
3)命令行连接任意一台redis服务器查看数据(在任意主机连接redis服务器都可以)
[root@host52 ~]# redis-cli -c -h 192.168.4.51 -p 6379
192.168.4.51:6379> keys *
1) "j"
192.168.4.51:6379> exit
[root@host52 ~]# redis-cli -c -h 192.168.4.52 -p 6379
192.168.4.52:6379> keys *
1) "k"
2) "name"
192.168.4.52:6379> exit
[root@host52 ~]# redis-cli -c -h 192.168.4.53 -p 6379
192.168.4.53:6379> keys *
1) "i"
192.168.4.53:6379>
案例3:数据迁移 (把存储在读写分离结构里的数据 复制到 PXC集群结构里)
在线迁移数据(在网站业务不停止的情况下复制数据到新的存储结构pxc集群里)
步骤一:配置从服务器(把主机192.168.4.66 配置为192.168.4.11的从服务器)
1)在192.168.4.66主机安装数据库服务软件并启动mysqld服务(mysql-5.7.17)
启动mysql服务 , 查看初始密码 登陆后 修改密码 退出 使用新密码登陆
[root@pxcnode66 ~]# tar -xf mysql-5.7.17.tar //解包
[root@pxcnode66 ~]# yum -y install mysql-community-*.rpm //安装软件
[root@pxcnode66 ~]# systemctl start mysqld //启动服务
[root@pxcnode66 ~]# grep password /var/log/mysqld.log //查看初始密码
2019-07-05T01:56:51.895852Z 1 [Note] A temporary password is generated for root@localhost: bB0*uCmu:.Kj
[root@pxcnode66 ~]# mysql -uroot -p'bB0*uCmu:.Kj' //初始密码登录
mysql>
mysql> alter user root@"localhost" identified by "123qqq...A";//修改登录密码
Query OK, 0 rows affected (0.01 sec)
mysql>
mysql> exit //断开连接
Bye
[root@pxcnode66 ~]# mysql -uroot -p123qqq...A //新密码登录
2)修改服务主配置文件
[root@pxcnode66 ~]# vim /etc/my.cnf
[mysqld]
server_id=66 //指定server_id
:wq
[root@pxcnode66 ~]# systemctl restart mysqld //重启服务
3)确保数据一致 (pxcnode66主机 使用mysql11主机的完全备份恢复数据确保数据一致 )
3.1 先在 mysql11主机安装在线热备工具innobackupex 命令
把备份文件拷贝给 从服务pxc66主机
[root@mysql11 ~]# yum -y install libev-4.15-1.el6.rf.x86_64.rpm //安装依赖软件
[root@mysql11 ~]# yum -y install percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm //安装在线热备软件
[root@mysql11 ~]# innobackupex -uroot -p123qqq...A /allbak --no-timestamp //备份所有数据,并记录备份数据对应的binlog日志名
[root@mysql11 ~]# scp -r /allbak [email protected]:/root/ //把备份文件发送给pxcnode66主机
3.2 从服务pxc66主机 是完全备份文件恢复数据,(也要安装
热备工具innobackupex 命令)
[root@pxcnode66 ~]# yum -y install libev-4.15-1.el6.rf.x86_64.rpm //安装依赖软件
[root@pxcnode66 ~]# yum -y install percona-xtrabackup-24-2.4.7-1.el7.x86_64.rpm //安装在线热备软件
[root@pxcnode66 ~]# systemctl stop mysqld //停止服务
[root@pxcnode66 ~]# rm -rf /var/lib/mysql/* //清空数据库目录
[root@pxcnode66 ~]# innobackupex --apply-log /root/allbak/ //准备恢复数据
[root@pxcnode66 ~]# innobackupex --copy-back /root/allbak/ //恢复数据
[root@pxcnode66 ~]# chown -R mysql:mysql /var/lib/mysql //修改所有者
[root@pxcnode66 ~]# systemctl start mysqld //启动服务
4)指定主服务器 (把pxc66 配置为 mysql11 的从服务器)
在备份文件里查看 完全备份后 对应的日志名和偏移量
[root@pxc66 ~]# grep master11 /root/allbak/xtrabackup_info
binlog_pos = filename 'master11.000001', position '5543'
[root@pxc66 ~]#
[root@pxcnode66 ~]# mysql -uroot -p123qqq...A //管理员登录指定主服务器信息
mysql> change master to
master_host="192.168.4.11", //主服务器ip地址
master_user="repluser", //主服务器授权用户
master_password="123qqq...A", //授权密码
master_log_file="master11.000001", //binlog日志名
master_log_pos=2224; //日志偏移量
Query OK, 0 rows affected, 2 warnings (0.31 sec)
mysql> start slave ;
mysql> exit //断开连接
Bye
[root@pxcnode66 ~]#
[root@pxcnode66 ~]# mysql -uroot -p123qqq...A -e "show slave status\G" | grep -i 192.168.4.11 //查看主服务器地址
mysql: [Warning] Using a password on the command line interface can be insecure.
Master_Host: 192.168.4.11 //主服务器ip地址
[root@pxcnode66 ~]# mysql -uroot -p123qqq...A -e "show slave status\G" | grep -i "yes" //查看状态信息
mysql: [Warning] Using a password on the command line interface can be insecure.
Slave_IO_Running: Yes //IO线程正常
Slave_SQL_Running: Yes //SQL线程正常
[root@pxcnode66 ~]#
步骤二:配置第1台PXC服务器(192.168.4.66)
1)停止mysqld服务、卸载mysqld服务软件
[root@pxc66 ~]# systemctl stop mysqld
[root@pxc66 ~]# rpm -e --nodeps mysql-community-common mysql-community-devel \
mysql-community-test mysql-community-minimal-debuginfo \
mysql-community-libs mysql-community-server mysql-community-embedded \
mysql-community-embedded-devel mysql-community-embedded-compat \
mysql-community-client mysql-community-libs-compat
2)安装PXC软件、修改配置文件、启动mysql服务
[root@pxcnode66 ~]# cd PXC //进软件目录
[root@pxcnode66 PXC]# yum -y install libev-4.15-1.el6.rf.x86_64.rpm
[root@pxcnode66 PXC]# yum -y install percona-xtrabackup-24-2.4.13-1.el7.x86_64.rpm qpress-1.1-14.11.x86_64.rpm
[root@pxcnode66 PXC]# yum -y install qpress-1.1-14.11.x86_64.rpm //安装依赖
[root@pxcnode66 PXC]# tar -xf Percona-XtraDB-Cluster-5.7.25-31.35-r463-el7-x86_64-bundle.tar //解压PXC软件包
[root@pxcnode66 PXC]# yum -y install Percona-XtraDB-Cluster-*.rpm //安装软件
[root@pxcnode66 PXC]# vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf //修改数据库服务配置文件
[mysqld]
server-id=66 //指定server_id
:wq
[root@pxcnode66 PXC]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf //修改集群服务配置文件
8: wsrep_cluster_address=gcomm:// 不需要写ip地址
25: wsrep_node_address=192.168.4.66 //指定本机Ip地址
27: wsrep_cluster_name=pxc-cluster //指定集群名称(另外2台的集群名称要于此相同)
30: wsrep_node_name=pxcnode66 //指定本机主机名
39: wsrep_sst_auth="sstuser:123qqq…A" //数据全量同步授权用户及密码
:wq
[root@pxcnode66 PXC]#
[root@pxcnode66 PXC]# systemctl start mysql //启动服务
[root@pxcnode66 PXC]# mysql -uroot -p123qqq...A //管理员登录
mysql> grant all on *.* to sstuser@"localhost" identified by "123qqq...A"; //用户授权
mysql> exit;
步骤三:配置第2台PXC服务器(192.168.4.10)
1)安装PXC软件
2) 修改配置文件
3) 启动mysql服务
[root@pxcnode10 ~]# cd PXC //进软件目录
[root@pxcnode10 PXC]# yum -y install libev-4.15-1.el6.rf.x86_64.rpm
[root@pxcnode10 PXC]# yum -y install percona-xtrabackup-24-2.4.13-1.el7.x86_64.rpm qpress-1.1-14.11.x86_64.rpm
[root@pxcnode10 PXC]# yum -y install qpress-1.1-14.11.x86_64.rpm //安装依赖
[root@pxcnode10 PXC]# tar -xf Percona-XtraDB-Cluster-5.7.25-31.35-r463-el7-x86_64-bundle.tar //解压PXC软件包
[root@pxcnode10 PXC]# yum -y install Percona-XtraDB-Cluster-*.rpm //安装软件
[root@pxcnode10 PXC]# vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf //修改数据库服务配置文件
[mysqld]
server-id=10 //指定server_id
:wq
[root@pxcnode10 PXC]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf //修改集群服务配置文件
8: wsrep_cluster_address=gcomm://192.168.4.66
25: wsrep_node_address=192.168.4.10 //指定本机Ip地址
27: wsrep_cluster_name=pxc-cluster //指定集群名称(另外2台的集群名称要于此相同)
30: wsrep_node_name=pxcnode10 //指定本机主机名
39: wsrep_sst_auth="sstuser:123qqq…A" //数据全量同步授权用户及密码
:wq
[root@pxcnode10 PXC]# systemctl start mysql //启动服务
[root@pxcnode10 PXC]# mysql -uroot -p123qqq...A //管理员登录
步骤三:配置第3台PXC服务器(192.168.4.88)
1)安装PXC软件
2) 修改配置文件
3) 启动mysql服务
[root@pxcnode88 ~]# cd PXC //进软件目录
[root@pxcnode88 PXC]# yum -y install libev-4.15-1.el6.rf.x86_64.rpm
[root@pxcnode88 PXC]# yum -y install percona-xtrabackup-24-2.4.13-1.el7.x86_64.rpm qpress-1.1-14.11.x86_64.rpm
[root@pxcnode88 PXC]# yum -y install qpress-1.1-14.11.x86_64.rpm //安装依赖
[root@pxcnode88 PXC]# tar -xf Percona-XtraDB-Cluster-5.7.25-31.35-r463-el7-x86_64-bundle.tar //解压PXC软件包
[root@pxcnode88 PXC]# yum -y install Percona-XtraDB-Cluster-*.rpm //安装软件
[root@pxcnode88 PXC]# vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf //修改数据库服务配置文件
[mysqld]
server-id=88 //指定server_id
:wq
[root@pxcnode88 PXC]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf //修改集群服务配置文件
8: wsrep_cluster_address=gcomm://192.168.4.66
25: wsrep_node_address=192.168.4.88 //指定本机Ip地址
27: wsrep_cluster_name=pxc-cluster //指定集群名称(另外2台的集群名称要于此相同)
30: wsrep_node_name=pxcnode88 //指定本机主机名
39: wsrep_sst_auth="sstuser:123qqq…A" //数据全量同步授权用户及密码
:wq
[root@pxcnode88 PXC]# systemctl start mysql //启动服务
[root@pxcnode88 PXC]# mysql -uroot -p123qqq...A //管理员登录
步骤五:公共配置(192.168.4.88、192.168.4.10、192.168.4.66)
pxcnode66~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
wsrep_cluster_address=gcomm://192.168.4.66,192.168.4.10,192.168.4.88 //指定集群成员列表
:wq
pxcnode10~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
wsrep_cluster_address=gcomm://192.168.4.66,192.168.4.10,192.168.4.88 //指定集群成员列表
:wq
pxcnode88~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
wsrep_cluster_address=gcomm://192.168.4.66,192.168.4.10,192.168.4.88 //指定集群成员列表
:wq
测试配置
[root@mysql11 ~]# mysql -uroot -p123qqq...A
#访问pxc集群存储数据需要表中有主键字段
mysql> alter table gamedb.user add id int primary key auto_increment first;
mysql> exit;
[root@web33 ~]# mysql -h192.168.4.66 -uyaya -p123qqq...A gamedb
Mysql> insert into gamedb.user(name) values ("pljA");
Mysql> exit ;
[root@web33 ~]# mysql -h192.168.4.10 -uyaya -p123qqq...A gamedb
Mysql> insert into gamedb.user(name) values ("pljB");
Mysql> exit ;
[root@web33 ~]# mysql -h192.168.4.88 -uyaya -p123qqq...A gamedb
Mysql> insert into gamedb.user(name) values ("pljC");
Mysql> exit ;
#网站服务33 连接集群中的任意一台服务器都可以查看到 插入的 所有数据
[root@web33 ~]# mysql -h192.168.4.66 -uyaya -p123qqq...A -e 'select * from gamedb.user'
[root@web33 ~]# mysql -h192.168.4.10 -uyaya -p123qqq...A -e 'select * from gamedb.user'
[root@web33 ~]# mysql -h192.168.4.88 -uyaya -p123qqq...A -e 'select * from gamedb.user'
案例4:部署LB集群
步骤一:安装软件: 在haproxy99主机上安装haproxy软件
步骤二:修改配置文件
步骤三:启动服务
步骤四:测试配置:在网站服务器连接haproxy99主机访问数据
[root@haproxy99 ~]# yum -y install haproxy
[root@haproxy99 ~]# vim /etc/haproxy/haproxy.cfg
#文件末尾添加如下行
listen mysql_3306 *:3306 //定义haproxy服务名称与端口号
mode tcp //mysql服务 得使用 tcp 协议
option tcpka //使用长连接
balance roundrobin //调度算法
server mysql_01 192.168.4.66:3306 check //第1台数据库服务器
server mysql_02 192.168.4.10:3306 check //第2台数据库服务器
server mysql_03 192.168.4.88:3306 check //第3台数据库服务器
:wq
[root@haproxy99 haproxy]#
[root@haproxy99 ~]# systemctl start haproxy //启动服务
[root@haproxy99 ~]# netstat -utnlp | grep :3306 //查看端口
tcp6 0 0 :::3306 :::* LISTEN 29768/haproxy
测试配置
[root@web33 ~]# mysql -h192.168.4.99 -uyaya -p123qqq...A -e ‘select @@hostname’
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| pxcnode66 | //第1次连接
+------------+
[root@web33 ~]#
[root@web33 ~]# mysql -h192.168.4.99 -uyaya -p123qqq…A -e ‘select @@hostname’
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| pxcnode10 | //第2次连接
+------------+
[root@web33 ~]#
[root@web33 ~]# mysql -h192.168.4.99 -uyaya -p123qqq…A -e ‘select @@hostname’
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| pxcnode88 | //第3次连接
+------------+
[root@web33 ~]#
案例5:部署HA集群
步骤一:准备备用调度器主机192.168.4.98
环境准备: 创建新的虚拟机 并配置ip地址 192.168.4.98
1) 安装haproxy 软件
[root@haproxy98 ~]#yum -y install haproxy
2)修改haproxy98主机haproxy.conf文件
说明要和99主机的配置一样,所以直接拷贝haproxy99主机的配置文件也可以
[root@haproxy98 ~]#scp /etc/haproxy/haproxy.cfg 192.168.4.98:/etc/haproxy/
3)启动haproxy服务
[root@haproxy98 ~]# systemctl start haproxy
[root@haproxy98 ~]# netstat -utnalp | grep 3306
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 918/haproxy
[root@haproxy98 ~]#
步骤二:安装软件keepalived软件
1)在haproxy99主机安装keepalived软件
[root@haproxy99 ~]# yum -y install keepalived.x86_64
2)在haproxy98主机安装keepalived软件
[root@haproxy98 ~]# yum -y install keepalived.x86_64
步骤三:修改配置文件
1)修改haproxy99主机的配置文件,说明99主机做主调度器 优先级要比98高
#删除文件中不相关的配置
[root@haproxy99 ~]# sed -i '36,$d' /etc/keepalived/keepalived.conf
[root@haproxy99 ~]# vim /etc/keepalived/keepalived.conf
.....
......
vrrp_iptables
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.4.100
}
}
:wq
2)修改haproxy98主机的配置文件,说明98主机做备用调度器 优先级要比99低
[root@haproxy98 ~]# scp [email protected]:/etc/keepalived/keepalived.conf /etc/keepalived/
[root@haproxy98 ~]# vim /etc/keepalived/keepalived.conf
....
state BACKUP
....
priority 100
:wq
步骤四:启动服务
1)在haproxy99主机启动keepalived服务
[root@haproxy99 ~]# systemctl start keepalived
2)在haproxy98主机启动keepalived服务
[root@haproxy98 ~]# systemctl start keepalived
步骤五:测试配置
1)客户端连接vip地址,访问数据库服务
[root@web33 ~]# mysql -h192.168.4.100 -uyaya -p123qqq...A -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| pxc10 |
+------------+
[root@web33 ~]# mysql -h192.168.4.100 -uyaya -p123qqq...A -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| pxc88 |
+------------+
[root@web33 ~]# mysql -h192.168.4.100 -uyaya -p123qqq...A -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
2)测试高可用
#把99主机的keepalived 服务停止模拟 服务宕机里
[root@haproxy99 ~]# systemctl stop keepalived
#在98 主机可以查看到vip地址 192.168.4.100
[root@haproxy98 ~]# ip addr show | grep 192
inet 192.168.4.98/24 brd 192.168.4.255 scope global noprefixroute eth0
inet 192.168.4.100/32 scope global eth0
[root@haproxy98 ~]#
#客户端一直连接vip地址访问数据库服务
[root@web33 ~]# mysql -h192.168.4.100 -uyaya -p123qqq...A -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| pxc66 |
+------------+
[root@web33 ~]# mysql -h192.168.4.100 -uyaya -p123qqq...A -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| pxc10 |
+------------+
[root@web33 ~]# mysql -h192.168.4.100 -uyaya -p123qqq...A -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
ip地址 | 角色 | 主机名 | 安装软件 | 启动服务 | 备注 | |
---|---|---|---|---|---|---|
day01 | 192.168.4.33(clone-vm7) | 网站服务器 | web33 | tomcat | 否 | 无 |
192.168.4.11(clone-mysql) | MySQL数据库服务器 | mysql11 | mysql-5.7.17 | 否 | 添加2块3G磁盘 | |
192.168.4.22(clone-mysql) | MySQL数据库服务器 | mysql22 | mysql-5.7.17 | 否 | 添加2块3G磁盘 | |
192.168.4.77(clone-vm7) | 数据读写分离服务器 | maxscale77 | maxscale | 否 | 无 | |
192.168.4.30(clone-vm7) | NFS服务器 | nfs30 | nfs-utlis rpcbind | 否 | 添加1块3G磁盘(如果硬件配置低,可以在77主机配置) | |
day02 | 192.168.4.51 | redis服务器 | redisA | redis | 是 | 启用集群功能 不需要设置连接密码 使用6379端口 |
192.168.4.52 | redis服务器 | redisB | redis | 是 | 启用集群功能 不需要设置连接密码 使用6379端口 | |
192.168.4.53 | redis服务器 | redisC | redis | 是 | 启用集群功能 不需要设置连接密码 使用6379端口 | |
192.168.4.54 | redis服务器 | redisD | redis | 是 | 启用集群功能 不需要设置连接密码 使用6379端口 | |
192.168.4.55 | redis服务器 | redisE | redis | 是 | 启用集群功能 不需要设置连接密码 使用6379端口 | |
192.168.4.56 | redis服务器 | redisF | redis | 是 | 启用集群功能 不需要设置连接密码 使用6379端口 | |
192.168.4.57 | redis集群管理主机 | MGM57 | 无 | 无 | 创建redis-trib.rb脚本(也可用77主机做管理主机) | |
192.168.4.66 | pxc集群主机 | host66 | mysql-5.7.17 | 否 | 无 | |
192.168.4.10 | pxc集群主机 | pxc10 | PXC集群软件 | 否 | 无 | |
192.168.4.88 | pxc集群主机 | pxc88 | PXC集群软件 | 否 | 无 | |
192.168.4.99 | LB集群调度器 | haproxy99 | haproxy软件 | 否 | 如果硬件配置低,可以在77主机配置 | |
192.168.4.98 | LB集群备用调度器 | haproxy98 | haproxy软件 | 否 | 如果硬件配置低,可以在30主机配置 |