1. 完成将server和client端的mysql配置默认字符集为utf8mb4;
vim /etc/my.cnf
[mysqld]
character-set-server=utf8mb4
[client]
default-character-set=utf8mb4
[root@localhost ~]#mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.68-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> SHOW VARIABLES LIKE '%char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
2. 掌握如何获取SQL命令的帮助,基于帮助完成添加testdb库,字符集utf8, 排序集合utf8_bin
MariaDB [(none)]> help create database
Name: 'CREATE DATABASE'
Description:
Syntax:
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_specification] ...
create_specification:
[DEFAULT] CHARACTER SET [=] charset_name
| [DEFAULT] COLLATE [=] collation_name
CREATE DATABASE creates a database with the given name. To use this
statement, you need the CREATE privilege for the database. CREATE
SCHEMA is a synonym for CREATE DATABASE.
URL: http://dev.mysql.com/doc/refman/5.5/en/create-database.html
MariaDB [(none)]> create database testdb character set utf8 coallate utf8_bin;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'coallate utf8_bin' at line 1
MariaDB [(none)]> create database testdb character set utf8 collate utf8_bin;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> show create database testdb
-> ;
+----------+----------------------------------------------------------------------------------+
| Database | Create Database |
+----------+----------------------------------------------------------------------------------+
| testdb | CREATE DATABASE `testdb` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */ |
+----------+----------------------------------------------------------------------------------+
1 row in set (0.00 sec)
3.总结mysql常见的数据类型。
数值型
整数型:
tinyint :1个字节 unsigned规定只为正数,0-255,默认正负128
小数型:
浮点型 float
定点数 decimal
字符型
char (定长)
varchar (不定长)
修饰符
适用所有类型
NULL : 数据中允许出现null
NOT NULL: 数据不允许出现null
DEFAULT : 默认值
PRIMARY KEY : 主键,所有字段的值不能重复,且不能为null
UNIQUE KEY : 唯一键
CHARACTER SET name : 指定一个字符集
适用数值型
AUTO_INCREMENT :自动递增
UNSIGNED :无符号
4. 创建一个主机表host,放在testdb中,要求字段 1) 主键自增id 无符号, tinyint. 2) hostname可变字符长度256,可为空。。3)ip 可变字符长度256,可为空。4)账号,可变字符长度256,可为空。5)密码,可变字符长度256,可为空。6)创建时间,时间类型,非空。7)更新时间,时间类型,默认当前时间。8)区域,只能在华南,华北,华东,三个区域之一。9)端口,无符号整数,可为空。10)外网地址,可变字符长度256,可为空。11)内网地址,可变字符长度256,可为空。
mysql> use testdb
Database changed
mysql> create table host (id tinyint unsigned primary key auto_increment, hostname varchar(256) null,ip varchar(256) null,password varchar(256),account varchar(256),creationtime datetime not null,updatetime datetime,region enum('south china','north china','east china'),port tinyint unsigned,,internetaddress varchar(256),insidenetwork varchar(256) );
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| host |
+------------------+
1 row in set (0.00 sec)
mysql> desc host;
+-----------------+------------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+------------------------------------------------+------+-----+---------+----------------+
| id | tinyint unsigned | NO | PRI | NULL | auto_increment |
| hostname | varchar(256) | YES | | NULL | |
| ip | varchar(256) | YES | | NULL | |
| password | varchar(256) | YES | | NULL | |
| account | varchar(256) | YES | | NULL | |
| creationtime | datetime | NO | | NULL | |
| updatetime | datetime | YES | | NULL | |
| region | enum('south china','north china','east china') | YES | | NULL | |
| port | tinyint unsigned | YES | | NULL | |
| internetaddress | varchar(256) | YES | | NULL | |
| insidenetwork | varchar(256) | YES | | NULL | |
+-----------------+------------------------------------------------+------+-----+---------+----------------+
11 rows in set (0.00 sec)
5. 给testdb.host表中添加多条数据。
mysql> insert into host (id,creationtime,region) values(1,'2022-01-01 12:40','north china');
Query OK, 1 row affected (0.00 sec)
mysql> insert into host (creationtime,region) values('2022-01-02 1:40','east china');
Query OK, 1 row affected (0.00 sec)
mysql> insert into host (creationtime,region) values('2022-01-05 11:40','south china');
Query OK, 1 row affected (0.00 sec)
mysql> select * from host;
+----+----------+------+----------+---------+---------------------+------------+-------------+------+-----------------+---------------+
| id | hostname | ip | password | account | creationtime | updatetime | region | port | internetaddress | insidenetwork |
+----+----------+------+----------+---------+---------------------+------------+-------------+------+-----------------+---------------+
| 1 | NULL | NULL | NULL | NULL | 2022-01-01 12:40:00 | NULL | north china | NULL | NULL | NULL |
| 2 | NULL | NULL | NULL | NULL | 2022-01-02 01:40:00 | NULL | east china | NULL | NULL | NULL |
| 3 | NULL | NULL | NULL | NULL | 2022-01-05 11:40:00 | NULL | south china | NULL | NULL | NULL |
+----+----------+------+----------+---------+---------------------+------------+-------------+------+-----------------+---------------+
3 rows in set (0.00 sec)
6. 根据表扩展出几个语句,完成总结DDL, DML的用法,并配上示例。
DDL
创建表
mysql> use testdb
Database changed
#创建host表
mysql> create table host (id tinyint unsigned primary key auto_increment, hostname varchar(256) null,ip varchar(256) null,password varchar(256),account varchar(256),creationtime datetime not null,updatetime datetime,region enum('south china','north china','east china'),port tinyint unsigned,internetaddress varchar(256),insidenetwork varchar(256) );
Query OK, 0 rows affected (0.01 sec)
查看表
mysql> show tables; #查看表
+------------------+
| Tables_in_testdb |
+------------------+
| host |
+------------------+
1 row in set (0.00 sec)
mysql> select * from host;
+----+----------+------+----------+---------+---------------------+------------+-------------+------+-----------------+---------------+
| id | hostname | ip | password | account | creationtime | updatetime | region | port | internetaddress | insidenetwork |
+----+----------+------+----------+---------+---------------------+------------+-------------+------+-----------------+---------------+
| 1 | NULL | NULL | NULL | NULL | 2022-01-01 12:40:00 | NULL | north china | NULL | NULL | NULL |
| 2 | NULL | NULL | NULL | NULL | 2022-01-02 01:40:00 | NULL | east china | NULL | NULL | NULL |
| 3 | NULL | NULL | NULL | NULL | 2022-01-05 11:40:00 | NULL | south china | NULL | NULL | NULL |
+----+----------+------+----------+---------+---------------------+------------+-------------+------+-----------------+---------------+
3 rows in set (0.00 sec)
mysql> desc host; #查看表结构
+-----------------+------------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+------------------------------------------------+------+-----+---------+----------------+
| id | tinyint unsigned | NO | PRI | NULL | auto_increment |
| hostname | varchar(256) | YES | | NULL | |
| ip | varchar(256) | YES | | NULL | |
| password | varchar(256) | YES | | NULL | |
| account | varchar(256) | YES | | NULL | |
| creationtime | datetime | NO | | NULL | |
| updatetime | datetime | YES | | NULL | |
| region | enum('south china','north china','east china') | YES | | NULL | |
| port | tinyint unsigned | YES | | NULL | |
| internetaddress | varchar(256) | YES | | NULL | |
| insidenetwork | varchar(256) | YES | | NULL | |
+-----------------+------------------------------------------------+------+-----+---------+----------------+
11 rows in set (0.00 sec)
mysql> SHOW TABLE STATUS\G; #纵向查看表状态
*************************** 1. row ***************************
Name: host
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 2
Avg_row_length: 8192
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 4
Create_time: 2022-11-21 22:02:09
Update_time: NULL
Check_time: NULL
Collation: utf8_bin
Checksum: NULL
Create_options:
Comment:
1 row in set (0.01 sec)
mysql> SHOW TABLE STATUS like 'host'\G #只查看host表状态
*************************** 1. row ***************************
Name: host
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 2
Avg_row_length: 8192
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 4
Create_time: 2022-11-21 22:02:09
Update_time: NULL
Check_time: NULL
Collation: utf8_bin
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
select count(*) from host;
删除表
mysql> drop table host1;
Query OK, 0 rows affected (0.01 sec)
修改表
mysql> alter table host rename host1; #修改表名
mysql> alter table host add phone varchar(11) after region; #添加字段
mysql> update host set port = 33 where id = 2; #修改id为2的端口为33
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> delete from host where id>=3; #删除host表中id大于等于3的行
Query OK, 1 row affected (0.00 sec)
mysql> update host set id=3 where id=4;
[root@firewall ~]#mysql -U testdb #安全更新模式,防止误删除
delete from host; #清空表
OPTIMIZE TABLE host; #缩减空间
DML
添加行
mysql> insert into host (id,creationtime,region) values(1,'2022-01-01 12:40','north china');
Query OK, 1 row affected (0.00 sec)
mysql> insert into host (creationtime,region) values('2022-01-02 1:40','east china'),('2022-01-05 11:40','south china');
Query OK, 2 rows affected (0.00 sec)
7. 导入hellodb库,总结DQL, alias, where子句,gruop by, order by, limit, having使用示例。
#alias
mysql> select Stuid 学号,Name 姓名,Age 年龄 from students;
#where
mysql> select * from students where Age <= 20;
mysql> select * from students where Age <= 20 and gender = 'F';
mysql> select * from students where Age <= 20 or gender = 'F';
mysql> select * from students where classid in (1,2,3);
mysql> select * from students where age between 20 and 30;
#limit 显示前几个
mysql> select * from students limit 3;
mysql> select * from students limit 2,3;
mysql> select * from students where classid is null;
mysql> select * from students where name = 'ma chao';
mysql> select * from students where name like 'x%';
mysql> select distinct age from students; #去重
mysql> select avg(age) from students; #平均年龄
#分组 group by
mysql> select gender,avg(age) from students group by gender; #分别计算男生和女生平均年龄
mysql> select gender,avg(age) from students group by gender having gender = 'M';
mysql> select gender,avg(age) from students where gender = 'F' group by gender;
mysql> select classid,gender,avg(age) from students group by classid,gender having classid is not null;
mysql> select gender,max(age) from students group by gender;
#排序 order by
mysql> select * from students order by age; #正序
mysql> select * from students order by age desc; #倒序
mysql> select * from students order by age desc,classid; #按年龄倒序排序,年龄一样时按班级排序
mysql> select * from students order by age desc limit 10; #挑出年龄最大前十个
8. 基于hellodb 库, 总结子查询,关联查询 ,交叉连接,内连接,左连接,右连接,完全连接,自连接。
子查询
子查询
update teachers set age=(select max(age) from students) where tid=3;
select * from teachers where age = (select max(age) from students);
关联查询
纵向合并
mysql> select stuid,name,age,gender from students
-> union
-> select * from teachers;
交叉连接
select * from students cross join teachers;
内连接
mysql> select t.tid,t.name,s.stuid,s.name from students s inner join teachers t on s.stuid=t.tid ;
mysql> select st.stuid,st.name,sc.score,co.course from students st inner join scores sc on sc.stuid=st.stuid inne
左连接
select * from students s left outer join teachers t on s.teacherid=t.tid;
右连接
select * from students s right outer join teachers t on s.teacherid=t.tid ;
完全连接
mysql> select * from students s left outer join teachers t on s.teacherid=t.tid
-> union
-> select * from students s right outer join teachers t on s.teacherid=t.tid ;
自连接
mysql> select e.name emp_name,IFNULL(l.name,'无上级') emp_leader from emp e left outer join emp l on e.leaderiid=l.id;
9. 总结select语句处理顺序。
SELECT语句执行流程
FROM Clause --> WHERE Clause --> GROUP BY--> HAVING Clause --> SELECT --> ORDER BY --> LIMIT
10. 总结mysql事件管理,用户管理,权限管理。
#创建用户
mysql> create user gao@'10.0.0.%' identified by '123456';
#更改密码
mysql> alter user gao@'10.0.0.%' identified by '654321';
#授权
mysql> grant all on testdb.* to gao@'10.0.0.%';
#刷新权限
flush privileges;
11. 基于apache, php, mysql搭建wordpress站点。
192.168.3.7 客户机
192.168.3.48 实现主服务器DNS
yum -y install bind
vim /etc/named.conf
options {
// listen-on port 53 { 127.0.0.1; }; #注释掉这两行
// allow-query { localhost; };
vim /etc/named.rfc1912.zones
#添加以下内容
zone "gao.com" {
type master;
file "gao.com.zone";
};
vim /var/named/gao.com.zone
$TTL 1D
@ IN SOA master admin.magedu.org ( 1 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS master
master A 192.168.3.48
blog A 192.168.3.8
chmod 640 /var/named/gao.com.zone
chgrp named /var/named/gao.com.zone
systemctl start named
#防火墙
eth0:10.0.0.8
eth1:192.168.3.8
[root@firewall ~]#iptables -t nat -A PREROUTING -d 192.168.10.8 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.7:80 #DNAT
eth0:10.0.0.58 lmp wordpress
在wordpress官网下载压缩包
unzip -d wordpress-6.1.1-zh_CN.zip -d /opt/
cd /opt/wordpress
yum -y install httpd php php-mysqlnd php-json
systemctl enable --now httpd
mv * /var/www/html/
chown -R apache. /var/www/html/
mysql -u wordpress -h 10.0.0.68 -p'123456'
eth0:10.0.0.68 mysql
create user wordpress@'10.0.0.%' identified by '123456';
grant all on wordpress.* to wordpress@'10.0.0.%'
12. 总结mysql架构原理
MySQL是C/S 架构的,
connectors是连接器;可供Native C API、JDBC、ODBC、NET、PHP、Perl.Python、Ruby、Cobol等连接mysql; ODBC叫开放数据库 (系统) 互联,open databaseconnection;DBC是主要用于java语言利用较为底层的驱动连接数据库:以上这些,站在编程角度可以理解为连入数据库管理系统的驱动,站在mysql角度称作专用语言对应的链接器.
任何链接器连入mysql以后,mysql是单进程多线程模型的,因此,每个用户连接,都会创建一个单独的连接线程;其实mysl连接也有长短连接两种方式,使用mysql客户端连入数据库后,直到使用quit命令才退出,可认为是长连接,使用mysql中的-e选项,在mysql客户端向服务器端申请运行一个命令后则立即退出,也就意味着连接会立即断开;所以,mysql也支持长短连接类似于两种类型,所以,用户连入mysql后,创建一个连接线程,完成之后,能够通过这个连接线程完成接收客户端发来的请求,为其处理请求,构建响应报文并发给客户端,由于是单进程模型,就意味着必须要维持一个线程池,跟之前介绍过的varnish很接近,需要一个线程池来管理这众多线程是如何对众多客户端的并发请求,完成并发响应的,组件connection pool就是实现这样功能。
connection pool对于mysql而言,它所实现的功能句括authentication认证,用户发来的账号密码是否正确要完成认证功能: thread reuse线程重用功能,一般当一个用户连接进来以后要用一个线程来响应它,而后当用户退出这个线程有可能并非被销毁,而是把它清理完以后,重新收归到线程池当中的空闲线程中去,以完成所谓的线程重用,connection limit 线程池的大小决定了连接并发数量的上限,例如,最多容纳100线程,一旦到达此上限后续到达的连接请求则只能排队或拒绝连接: check memory用来检测内存,caches实现线程缓存;整个都属于线程池的功能,当用户请求之后,通过线程池建立一个用户连接,这个线程一直存在,然后用户就通过这个会话,发送对应的SQL语句到服务器端.
服务器收到SQL语句后,要对语句完成执行,首先要能理解sql语句需要有sql解释器或叫接口sql interface就可理解为是整个mysql的外壳,就像shell是linux操作系统的外壳一样,用户无论通过哪种链接器发来的基本的SQL请求,当然,事实上通过native C API也有发过来的不是SQL 请求,而仅仅是对API中的传递参数后的调用: 不是SOL语句不过都统统理解为sgl语句罢了:对SOL而言分为DDL和DMI两种类型,但是无论哪种类型,提交以后必须交给内核,让内核来运行,在这之前必须要告诉内核哪个哪些是参数,是否存在语法错误等等;因此,这个整个SQL 接口就是一个完完整整的sql命令的解释器,并目这个sql接口还有提供完整的sql接口应该具备的功能,比如支持所谓过程式编程,支持代码块的实现像存诸过程、存储函数,触发器、必要时还要实现部署一个关系型数据库应该具备的基本组件例如视图等等,其实都在sql interface这个接口实现的;SQL接口做完词法分析、句法分析后,要分析语句如何执行让parser解析器或分析器实现
parser是专门的分析器,这个分析器并不是分析语法问题的,语法问题在sql接口时就能发现是否有错了,一个语句没有问题,就要做执行分析,所谓叫查询翻译,把一个查询语句给它转换成对应的能够在本地执行的特定操作;比如说看上去是语句而背后可能是执行的一段二进制指令,这个时候就完成对应的指令,还要根据用户请求的对象,比如某一字段查询内容是否有对应数据的访问权限,或叫对象访问权限,在数据库中库、表、字段、字段中的数据有时都称为obiect,叫一个数据库的对象,用户认证的通过,并不意味着就能一定能访问数据库上的所有数据,所以说,mysql的认证大概分为两过程都要完成,第一是连入时需要认证账号密码是否正确这是authentication,然后,验证成功后用户发来sq语还要验证用户是否有权限获取它期望请求获取的数据;这个称为obiect privilege,这一切都是由parsel分析器进行的
分析器分析完成之后,可能会生成多个执行树,这意味着为了能够达到访问期望访问到的目的,可能有多条路径都可实现,就像文件系统一样可以使用 图At+AE也可使用绝对路径,它有多种方式,在多种路径当中一定有一个是最优的,类似路由选择,因此,优化器就要去衡量多个访问路径中哪一个代价或开销是最小的,这个开销的计算要依赖于索引等各种内部组件来进行评估,而且这个评估的只是近似值同时还要考虑到当前mysql内部在实现资源访问时统计数据,比如,根据判断认为是1号路径的开销最!的,但是众多统计数据表明发往1号路径的访问的资源开销并不小,并且比3号路径大的多,因此,可能会依据3号路径访问;这就是所谓的优化器它负责检查多条路径,每条路径的开销,然后评估开销,这评估根据内部的静态数据,索引,根域根据动态生成的统计数据来判定每条路径的开销大小,因此这里还有statics;一旦优化完成之后,还要生成统计数据,这就是优化器的作用:如果没有优化器mysql执行语句是最慢的,其实优化还包括一种功能,一旦选择完一条路径后,例如用户给的这个命令执行起来,大概需要100个开销,如果通过改写语句能够达到同样目的可能只需要30个开销,于是,优化器还要试图改写sql语句;所以优化本身还包括查询语句的改写,一旦优化完成,接下来就交给存储引擎完成
mysgl是插件式存储引擎,它就能够替换使用选择多种不同的引擎,MyISAM是MVSQL 经典的存储引警一,InnoDB是由Innobase Ov公司所开发,2006年五月由甲骨文公司并购提供给MySOL的,NDB主要用于MysQL Cluster 分布式集群环境,archive做归档的等等,还有许多第三方开发的存储引擎;存储引擎负责把具体分析的结果完成对磁盘上文件路径访问的转换,数据库中的行数据都是存储在磁盘块上的,因此存储引擎要把数据库数据映射为磁盘块,并把磁盘块加载至内存中,进程实现数据处理时,是不可能直接访问磁盘上的数据的,因为它没有权限,只有让内核来把它所访问的数据加载至内存中以后,进程在内存中完成修改,由内核再负责把数据存回磁盘,对于文件系统而言,数据的存储都是以磁盘块方式存储的,但是,mysql在实现数据组织时,不完全依赖于磁盘,而是把磁盘块再次组织成更大级的逻辑单位,类似于vm中的PE或LE的形式,其实,MySQL的存储引警在实现数据管理时,也是在文件系统之上布设文件格式,对于文件而言在逻辑层上还会再次组织成一个逻辑单位,这个逻辑单位称为myql的数据块datablock 一般为16k,对于关系型数据库,数据是按行存储的;一般一行数据都是存储在一起的,因此,MySQL 在内部有一个datablock,在datablock可能存储一行数据,也可能存放了n行数据;将来在查询加载一行数据时,内核会把整个一个数据数据块加载至内存中,而mysql存储引擎,就从中挑出来某一行返回给查询者,是这样实现的;所以整个存储是以datablock在底层为其最终级别的。
13. 总结myisam和Innodb存储引擎的区别。
Innodb 引擎 特点
行级锁
可缓存数据和索引
支持外键
支持MVCC(多版本并发控制机制)
支持事务
最大支持64TB
MySIAM
表级锁
不能缓存数据和索引
不支持外键
不支持MVCC
不支持事务
14. 总结mysql索引作用,同时总结哪些查询不会使用到索引。
索引作用
索引可以降低服务所需要扫描的数据量,减少了IO次数
索引可以帮助服务器避免排序和使用临时表
索引可以帮助将随机I/O转为顺序I/O
查询到的记录很多会不使用索引
查询无索引的字段不使用索引
查询姓名包含x,或以x结尾不使用索引,只有左前缀使用索引
15. 总结事务ACID事务特性
A:atomicity 原子性:整个事务中的所有操作要么全部成功执行,要么全部失败回滚
C:consitstency 一致性:数据库总是从一个一致性状态转换到另一个一致性状态,类似能量守恒状态
I:isolation 隔离性:一个事务所做出的操作再提交之前,是不能被其他事务所见
D:durability 持久性:一旦事务提交,其所做的修改永久保存在数据库中
16. 总结事务日志工作原理。
redo log: 记录某数据块被修改后的值,数据更新前先记录redo log(WALWrite Ahead Log),可以用来恢复未写入data file的已成功事务更新的数据
undo log: 保存和执行的操作相反的操作,即记录某数据被修改前的值,可以用来事务失败时进行rollback
17. 总结mysql日志类型,并说明如何启动日志。
事务日志: transaction log
vim /etc/my.cnf
[mysqld]
innodb_flush_log_at_trx_commit=0
innodb_log_file_size=500000000
innodb_log_files_in_group=3
innodb_log_group_home_dir=/data/tran_logs
错误日志: error log
vim /etc/my.cnf
[mysqld]
log_error=/data/log_error/mysqld.log
mkdir /data/log_error/ -p;chown mysql.mysql /data/log_error
systemctl restart mysqld
通用日志:general log
vim /etc/my.cnf
[mysqld]
general_log=on
systemctl restart mysqld
慢查询日志: slow query log
vim /etc/my.cnf
[mysqld]
slow_query_log=on
log_queries_not_using_indexes=on
systemctl restart mysqld
二进制日志:binary log
[root@firewall ~]#vim /etc/my.cnf
[mysqld]
#innodb_flush_log_at_trx_commit=0
#innodb_log_file_size=500000000
#innodb_log_files_in_group=3
#innodb_log_group_home_dir=/data/tran_logs
#log_error=/data/log_error/mysqld.log
#general_log
#slow_query_log
log_bin=/data/binlog/mysql-bin
sql_log_bin=on
[root@firewall ~]#mkdir -p /data/binlog/
[root@firewall ~]#chown mysql. /data/binlog/
[root@firewall ~]#systemctl restart mysqld
中继日志: reley log
18. 总结二进制日志的不同格式的使用场景。
set sql_log_bin=0 #还原数据或导入大批量的测试数据时
set sql_log_bin=1 #数据库正常工作时
binlog_format=ROW
基于“语句”记录:statement,记录语句,日志量较少,节约空间。
基于“行”记录:row,记录数据,日志量较大,更加安全 ,有助于还原数据。
混合模式:mixed,让系统自行判断基于哪种方式进行
19. 总结mysql备份类型,并基于mysqldump, xtrabackup完成数据库备份与恢复验证。
完全备份:整个数据集
部分备份:只备份数据子集
增量备份:仅备份最近一次完全备份或增量备份以来变化的数据,备份较快,还原复杂
差异备份:仅备份最近一次完全备份以来变化的数据,备份较慢,还原简单
冷、温、热备份
冷备:读、写操作均不可进行,数据库停止服务
温备:读操作可执行,但写操作不可执行
热备:读、写操作均可执行
物理和逻辑备份
物理备份:直接复制数据文件进行备份,与存储引擎有关,占用较多的空间,速度快
逻辑备份:从数据库中‘导出’数据另存而进行的备份,与存储引擎无关,占用空间少,速度慢
mysqldump实现备份还原
10.0.0.8
173 2022-11-23 16:18:57 mysqldump -uroot -F -A --single-transaction --master-data=2 > /data/full_`date +%F`.sql;
175 2022-11-23 16:19:45 vim /data/full_`date +%F`.sql
180 2022-11-23 16:22:00 mysql hellodb;
mysql> insert students (name,age,gender) values('libai',33,'M');
mysql> insert students (name,age,gender) values('yasuo',63,'M');
mysql> insert students (name,age,gender) values('kate',22,'F');
mysql> flush logs;
mysql> insert students (name,age,gender) values('jack',42,'M');
mysql> insert students (name,age,gender) values('rose',26,'F');
mysql> drop table students;
mysql> insert teachers (name,age,gender) values('zz',26,'F');
mysql> insert teachers (name,age,gender) values('giao',23,'M');
182 2022-11-23 16:32:41 mysqlbinlog --start-position=156 /data/binlog/mysql-bin.000011
183 2022-11-23 16:33:03 mysqlbinlog --start-position=156 /data/binlog/mysql-bin.000011 > /data/inc.sql
184 2022-11-23 16:33:50 mysqlbinlog /data/binlog/mysql-bin.000012 >> /data/inc.sql
185 2022-11-23 16:34:05 ll /data
186 2022-11-23 16:34:38 grep drop /data/inc.sql
187 2022-11-23 16:34:53 grep -i drop /data/inc.sql
188 2022-11-23 16:36:11 sed -n '/DROP TABLE `students` /p' /data/inc.sql
189 2022-11-23 16:36:30 sed -i '/DROP TABLE `students` /d' /data/inc.sql
190 2022-11-23 16:36:36 grep -i drop /data/inc.sql
191 2022-11-23 16:36:49 sed -n '/DROP TABLE `students` /p' /data/inc.sql
192 2022-11-23 16:37:59 scp /data/* 10.0.0.68:/data
10.0.0.68
[root@rocky8 ~]#mysql -uroot -p123456
mysql> set sql_log_bin=0;
mysql> source /data/full_2022-11-23.sql;
mysql> set sql_log_bin=1;
[root@firewall ~]#mysqldump -uroot -p -hlocalhost -B hellodb > /backup/hellodb_B.sql
Enter password:
[root@firewall ~]#ll /backup/*
-rw-r--r-- 1 root root 7799 Nov 23 10:06 /backup/hellodb_B.sql
-rw-r--r-- 1 root root 4266136 Nov 23 10:04 /backup/hellodb.sql
mysql> drop database hellodb;
Query OK, 7 rows affected (0.02 sec)
mysql> \. /backup/hello_B.sql
xtrabackup完成数据库备份与恢复验证
10.0.0.8 原主机
tar xvf Percona-XtraBackup-8.0.30-23-r873b467185c-el8-x86_64-bundle.tar
yum -y install percona-xtrabackup-80-8.0.30-23.1.el8.x86_64.rpm
mkdir /backup1
xtrabackup -uroot -p123456 --backup --target-dir=/backup1/base
10.0.0.68 目标主机
[root@rocky8 /]#tar xvf Percona-XtraBackup-8.0.30-23-r873b467185c-el8-x86_64-bundle.tar
[root@rocky8 /]#yum -y install percona-xtrabackup-80-8.0.30-23.1.el8.x86_64.rpm
[root@rocky8 /]#xtrabackup --prepare --target-dir=/backup1/base
[root@rocky8 /]#systemctl stop mysqld
[root@rocky8 mysql]#xtrabackup --copy-back --target-dir=/backup1/base
[root@rocky8 mysql]#chown -R mysql:mysql /var/lib/mysql
[root@rocky8 mysql]#systemctl start mysqld
20. 编写crontab,每天按表备份所有mysql数据。将备份数据放在以天为时间的目录下。
[root@firewall ~]#vim backup.sh
#!/bin/bash
DIR=/backup
TIME=`date +%F`
TIMEA=`date +%F_%H-%M-%S`
pass=808356
B=hellodb
mkdir ${DIR}/${TIME}
mysqldump -uroot $B students | gzip > ${DIR}/${TIME}/${B}.students_${TIMEA}.sql.g
chmod +x backup.sh
[root@firewall ~]#crontab -e
8 14 * * * /root/backup.sh
[root@firewall 2022-11-23]#ll
-rw-r--r-- 1 root root 1114 Nov 23 14:08 hellodb.students_2022-11-23_14-08-01.sql.gz
21. 编写crontab, 基于xtrabackup,每周1,周5进行完全备份,周2到周4进行增量备份。
[root@firewall backup]#crontab -e
0 14 * * 1,5 /usr/bin/xtrabackup -uroot -p123456 --backup --target-dir=/backup/base
0 15 * * 2 /usr/bin/xtrabackup -uroot -p123456 --backup --target-dir=/backup/inc1 --incremental-basedir=/backup/base
0 15 * * 3 /usr/bin/xtrabackup -uroot -p123456 --backup --target-dir=/backup/inc2 --incremental-basedir=/backup/inc1
0 15 * * 4 /usr/bin/xtrabackup -uroot -p123456 --backup --target-dir=/backup/inc3 --incremental-basedir=/backup/inc2
22. 总结mysql主从复制原理。
主节点开启二进制,
当主节点收到写操作,数据库更新数据,生成二进制,写进二进制日志中,自动开启dump线程,实时把主节点的二进制日志发送给从节点,从节点事先开启IO线程,IO线程接受从主节点dump线程发送的二进制日志,写入relay log,sql线程把relay log中数据读入,从而应用在数据库中,使数据库数据进行更新。
23. 实现mysql主从复制,主主复制,半同步复制,过滤复制,
主从复制
10.0.0.8 主节点
[root@firewall ~]#vim /etc/my.cnf
[mysqld]
log_bin=/data/binlog/mysql-bin
server-id=8
systemctl restart mysqld.service
mysql
mysql> create user repluser@'10.0.0.%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)
mysql> grant replication slave on *.* to repluser@'10.0.0.%';
Query OK, 0 rows affected (0.01 sec)
[root@firewall ~]#mysqldump -uroot -p -A -F --master-data --single-transaction > /backup/full_`date +%F`.sql
[root@firewall ~]#scp /backup/full_2022-11-23.sql 10.0.0.68:/backup
10.0.0.68 slave68
[root@rocky8 /]#vim /etc/my.cnf
[mysqld]
server-id=68
read-only
[root@rocky8 /]#systemctl restart mysqld.service
vim /backup/full_2022-11-23.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.8',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000015', MASTER_LOG_POS=156;
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /backup/full_2022-11-23.sql
mysql> set sql_log_bin=1;
mysql> start slave;
主主复制
10.0.0.8 主节点
[root@firewall ~]#vim /etc/my.cnf
[mysqld]
log_bin=/data/binlog/mysql-bin
server-id=8
systemctl restart mysqld.service
mysql
mysql> create user repluser@'10.0.0.%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)
mysql> grant replication slave on *.* to repluser@'10.0.0.%';
Query OK, 0 rows affected (0.01 sec)
[root@firewall ~]#mysqldump -uroot -p -A -F --master-data --single-transaction > /backup/full_`date +%F`.sql
[root@firewall ~]#scp /backup/full_2022-11-23.sql 10.0.0.68:/backup
mysql> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.68',
-> MASTER_USER='repluser',
-> MASTER_PASSWORD='123456',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mysql-bin.00003', MASTER_LOG_POS=156;
Query OK, 0 rows affected, 9 warnings (0.03 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)
10.0.0.68 slave68
[root@rocky8 /]#vim /etc/my.cnf
[mysqld]
server-id=68
read-only
[root@rocky8 /]#systemctl restart mysqld.service
vim /backup/full_2022-11-23.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.8',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000015', MASTER_LOG_POS=156;
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /backup/full_2022-11-23.sql
mysql> set sql_log_bin=1;
mysql> start slave;
半同步复制
10.0.0.8 master 8
10.0.0.8
[root@firewall data]#mysqldump -uroot -p -A --single-transaction --source-data=1 > /data/all.sql
[root@firewall ~]#cd /data/
[root@firewall data]#scp /data/all.sql 10.0.0.58:/data
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
[root@firewall data]#vim /etc/my.cnf
[mysqld]
log_bin=/data/binlog/mysql-bin
server-id=8
rpl_semi_sync_master_enabled
rpl_semi_sync_master_timeout=3000
[root@firewall ~]#systemctl restart mysqld.service
mysql> SHOW GLOBAL VARIABLES LIKE '%semi%';
+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 3000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.01 sec)
mysql> SHOW status LIKE '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 2 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
10.0.0.58 slave58
[root@rocky8 ~]#vim /etc/my.cnf
[mysqld]
server-id=58
rpl_semi_sync_slave_enabled
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
[root@rocky8 ~]#vim /data/all.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.8',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000017', MASTER_LOG_POS=156;
[root@rocky8 data]#mysql < all.sql
mysql> set global rpl_semi_sync_slave_enabled=1;
mysql> start slave;
[root@rocky8 ~]#scp /data/all.sql 10.0.0.68:/data
10.0.0.68 slave68
[root@rocky8 ~]#vim /etc/my.cnf
[mysqld]
server-id=68
rpl_semi_sync_slave_enabled
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
[root@rocky8 data]#systemctl restart mysqld.service
[root@rocky8 data]#mysql < all.sql
mysql> start slave;
过滤复制
10.0.0.58 slave68
[root@rocky8 data]#vim /etc/my.cnf
[mysqld]
server-id=68
rpl_semi_sync_slave_enabled
replicate_do_db=db1
replicate_do_db=db2
[root@rocky8 data]#systemctl restart mysqld.service
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb |
| wordpress |
| zabbix |
+--------------------+
10.0.0.8 master
mysql> create database db1;
Query OK, 1 row affected (0.00 sec)
mysql> create database db2;
Query OK, 1 row affected (0.00 sec)
mysql> use db1
Database changed
mysql> create table t1;
ERROR 4028 (HY000): A table must have at least one visible column.
mysql> create table t1(id int);
Query OK, 0 rows affected (0.01 sec)
mysql> create database db3;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| db3 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb |
| wordpress |
| zabbix |
10.0.0.68 slave 58
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| db3 |
| hellodb |
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb |
| wordpress |
| zabbix |
+--------------------+
11 rows in set (0.01 sec)
24. 总结GTID复制原理,并完成GTID复制集群。
GTID复制原理
开启GTI功能可以支持多DUMP线程的并发复制,而且在MYSQL5.6实现了基于库级别多SQL线程并发。在MySQL5.7利用GTID的Logic clock逻辑时钟。保证了同库级别下的事务顺序问题。即可以实现基于事务级别的并发回放。从而大大减少了同步的延迟。
同时GTID具有幂等性特性,即多次执行结果是一样的。
10.0.0.8
[root@firewall data]#vim /etc/my.cnf
[mysqld]
log_bin=/data/binlog/mysql-bin
server-id=8
gtid_mode=on
enforce_gtid_consistency
[root@firewall data]#systemctl restart mysqld.service
10.0.0.58
[root@rocky8 data]#vim /etc/my.cnf
[mysqld]
server-id=58
gtid_mode=on
enforce_gtid_consistency
[root@rocky8 ~]#systemctl restart mysqld.service
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> reset slave all;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.8',
-> MASTER_USER='repluser',
-> MASTER_PASSWORD='123456',
-> MASTER_PORT=3306,
-> MASTER_AUTO_POSITION=1;
mysql> show slave status\G;
mysql> start slave;
mysql> show slave status\G;
25. 总结主从复制不一致的原因,如何解决不一致,如何避免不一致
主从复制不一致原因
主库binlog格式为statement,同步到库执行后可能造成主从不一致。
主库执行更改前有执行set sql_log_bin=0,会使主库不记录binlog,从库也无法变更这部分数据
从节点未设置只读,误操作写入数据
主库或从库意外宕机,宕机可能会造成binlog或者relaylog文件出现损坏,导致主从不一致
主从实例版本不一致,特别是高版本是主,低版本为从的情况下,主数据库上面支持的功能,从数据库上面可能不支持该功能
主从sql_mode不一致
MySQL自身bug导致
主从不一致修复方法
将从库重新实现
使用percona-toolkid工具辅助
手动重建不一致的表
如何避免主从不一致
主库binlog采用ROW格式
主从实例数据库版本保持一致
主库做好账号权限把控,不可以执行set sql_log_bin=0
从库开启只读,不允许人为写入
定期进行主从一致性检验
26. 总结数据库水平拆分和垂直拆分
水平拆分
水平切分是按照某个字段的某种规则来分散到多个库之中,每个表包含一部分数据,简单来说,我们可以将数据的水平拆分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的行又切分到其他数据库中
优点:
拆分规则抽象良好,join操作基本都可以数据库完成
不存在单库大数据,高并发的性能瓶颈
应用端改造较少
提高了系统的稳定性和负载能力
缺点:
拆分规则难以抽象
分片事务一致性难以解决
数据多次扩展跟维护量极大
跨库join性能较差
共同的缺点
引入分布式事务的问题
跨节点join的问题
跨节点合并排序分页问题
多数据源管理问题
垂直拆分
垂直拆分是按照不同的表来切分到不同的数据库(主机)之上,最大特点是规则简单,实施也更为方便,尤其适合各业务之间的耦合度非常低,相互影响很小,业务逻辑非常清晰的系统。在这种系统中,可以很容易做到将不同业务模块所使用的表拆分到不同的数据库中。根据不同的表来进行拆分,对应用程序影响也更小,拆分规则比较简单清晰。
垂直切分优缺点
优点:
拆分后业务清晰,拆分规则明确
系统之间整合或扩展容易
数据维护简单
缺点:
部分业务表无法join,只能通过接口方式解决,提高了系统复杂度
受每种业务不同的限制存在单库性能瓶颈,不易数据扩展和性能提高
事务处理复杂
27. 基于mycat实现读写分离
已经实现主从复制10.0.0.8master,10.0.0.58 slave
10.0.0.28 mycat
[root@mycat ~]#mkdir /apps
[root@mycat ~]#ll
-rw-r--r-- 1 root root 21760812 May 11 2022 Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz
[root@mycat ~]#tar xf Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz -C /apps
[root@mycat ~]#vi /etc/profile.d/mycat.sh
#!/bin/bash
PATH=/apps/mycat/bin:$PATH
[root@mycat ~]#. /etc/profile.d/mycat.sh
[root@mycat ~]#free -h
total used free shared buff/cache available
Mem: 2.7Gi 221Mi 2.1Gi 8.0Mi 420Mi 2.3Gi
Swap: 2.0Gi 0B 2.0Gi
[root@mycat ~]#yum -y install java
[root@mycat ~]#mycat start
[root@mycat ~]#tail /apps/mycat/logs/wrapper.log
STATUS | wrapper | 2022/11/24 17:14:59 | --> Wrapper Started as Daemon
STATUS | wrapper | 2022/11/24 17:14:59 | Launching a JVM...
INFO | jvm 1 | 2022/11/24 17:15:00 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO | jvm 1 | 2022/11/24 17:15:00 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.
INFO | jvm 1 | 2022/11/24 17:15:00 |
INFO | jvm 1 | 2022/11/24 17:15:01 | MyCAT Server startup successfully. see logs in logs/mycat.log
[root@mycat ~]#vim /apps/mycat/conf/server.xml
<property name="handleDistributedTransactions">0</property>
<property name="serverPort">3306</property> <property name="managerPort">9066</property>
[root@mycat ~]#vim /apps/mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database="hellodb" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="host1" url="10.0.0.8:3306" user="admin"
password="123456">
<readHost host="host2" url="10.0.0.58:3306" user="admin" password="123456" />
</writeHost>
</dataHost>
</mycat:schema>
10.0.0.8 master
mysql> create user admin@'10.0.0.%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)
mysql> grant all on hellodb.* to admin@'10.0.0.%';
Query OK, 0 rows affected (0.00 sec)
mysql> select @@general_log
-> ;
+---------------+
| @@general_log |
+---------------+
| 0 |
+---------------+
1 row in set (0.00 sec)
mysql> set global general_log=1;
10.0.0.58 slave
mysql> set global general_log=1;
10.0.0.38 client
[root@localhost yum.repos.d]#yum -y install mariadb
[root@localhost yum.repos.d]#mysql -uroot -p123456 -h10.0.0.28
MySQL [TESTDB]> select @@server_id
-> ;
+-------------+
| @@server_id |
+-------------+
| 58 |
+-------------+
1 row in set (0.01 sec)
MySQL [TESTDB]> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | zz | 26 | F |
| 6 | giao | 23 | M |
| 7 | lang | 45 | M |
| 8 | zhaozilong | 33 | M |
| 9 | liuan | 91 | M |
| 10 | a | 91 | M |
| 11 | a | 91 | M |
+-----+---------------+-----+--------+
MySQL [TESTDB]> update teachers set age=@@server_id where tid=11;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MySQL [TESTDB]> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | zz | 26 | F |
| 6 | giao | 23 | M |
| 7 | lang | 45 | M |
| 8 | zhaozilong | 33 | M |
| 9 | liuan | 91 | M |
| 10 | a | 91 | M |
| 11 | a | 8 | M |
+-----+---------------+-----+--------+
11 rows in set (0.01 sec)
28. 总结mysql高可用方案及高可用级别,搭建MHA集群和galera cluster,尝试搭建TIDB集群。
Mysql 高可用级别
Method | Level of Availability |
Simjple replication | 98-99.9% |
Master-Master/MMM | 99% |
SAN | 99.5-99.9% |
DREB,MHA,Tungsten Replicator | 99.9% |
NBDCluster,Galera Cluster | 99.999% |
MHA集群
10.0.0.7 manager
yum -y install mha4mysql-manager-0.58-0.el7.centos.noarch.rpm mha4mysql-node-0.58-0.el7.centos.noarch.rpm
ssh 10.0.0.8
ssh 10.0.0.58
ssh 10.0.0.68
ssh 10.0.0.7
ssh-keygen
ssh-copy-id 127.0.0.1
rsync -a .ssh 10.0.0.8:/root/
rsync -a .ssh 10.0.0.58:/root/
rsync -a .ssh 10.0.0.68:/root/
mkdir /etc/mastermha/app1.conf
user=mhauser
password=magedu
manager_workdir=/data/mastermha/app1/
manager_log=/data/mastermha/app1/manager.log
remote_workdir=/data/mastermha/app1/
ssh_user=root
repl_user=repluser
repl_password=123456
ping_interval=1
master_ip_failover_script=/usr/local/bin/master_ip_failover
report_script=/usr/local/bin/sendmail.sh
check_repl_delay=0
master_binlog_dir=/data/mysql/
[server1]
hostname=10.0.0.8
candidate_master=1
[server2]
hostname=10.0.0.58
[server3]
hostname=10.0.0.68
candidate_master=1
masterha_check_ssh --conf=/etc/mastermha/app1.cnf
Fri Nov 25 15:09:50 2022 - [info] All SSH connection tests passed successfully.
masterha_check_repl --conf=/etc/mastermha/app1.cnf
MySQL Replication Health is OK.
masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover
[root@Centos ~]#tail /data/mastermha/app1/manager.log -f
Fri Nov 25 14:37:55 2022 - [info] Checking master_ip_failover_script status:
Fri Nov 25 14:37:55 2022 - [info] /usr/local/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=10.0.0.8 --orig_master_ip=10.0.0.8 --orig_master_port=3306
Checking the Status of the script.. OK
Fri Nov 25 14:37:55 2022 - [info] OK.
Fri Nov 25 14:37:55 2022 - [warning] shutdown_script is not defined.
Fri Nov 25 14:37:55 2022 - [info] Set master ping interval 1 seconds.
Fri Nov 25 14:37:55 2022 - [warning] secondary_check_script is not defined. It is highly recommended setting it to check master reachability from two or more routes.
Fri Nov 25 14:37:55 2022 - [info] Starting ping health check on 10.0.0.8(10.0.0.8:3306)..
Fri Nov 25 14:37:55 2022 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..
10.0.0.8 master
yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
[root@master ~]#vim /etc/my.cnf
[mysqld]
log_bin=/data/mysql/mysql-bin
server-id=8
skip_name_resolve=1
general_log
mkdir /data/mysql
chown mysql.mysql /data/mysql
systemctl restart mysqld
ifconfig eth0:1 10.0.0.100/24
create user repluser@'10.0.0.%' identified by '123456'
grant replication slave on *.* to repluser@'10.0.0.%'
create user mhauser@'10.0.0.%' identified by 'magedu'
grant all on *.* to mhauser@'10.0.0.%'
mysqldump -uroot -p -A --single-transaction --source-data=1 > /data/all.sql
scp /data/all.sql 10.0.0.58:/data
10.0.0.58 slave1 ,10.0.0.68同理 server-id=68
yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
[root@slave1 ~]#vim /etc/my.cnf
[mysqld]
server-id=58
read-only
log_bin=/data/mysql/mysql-bin
skip_name_resolve=1
general_log
relay_log_purge=0
mkdir /data/mysql
chown mysql.mysql /data/mysql
systemctl restart mysqld
mysql
set sql_bin_log=0;
source /data/all.log;
start slave;
galera cluster
10.0.0.7
[root@Centos yum.repos.d]#vim /etc/yum.repos.d/pxc.repo
[percona]
name=percona_repo
baseurl=https://mirror.tuna.tsinghua.edu.cn/percona/release/7/RPMS/x86_64/
enabled=1
gpgcheck=0
scp /etc/yum.repos.d/pxc.repo 10.0.0.38:/etc/yum.repos.d/pxc.repo
scp /etc/yum.repos.d/pxc.repo 10.0.0.48:/etc/yum.repos.d/pxc.repo
scp /etc/yum.repos.d/pxc.repo 10.0.0.47:/etc/yum.repos.d/pxc.repo
yum -y install Percona-XtraDB-Cluster-57
[root@Centos yum.repos.d]#vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
# Cluster connection URL contains IPs of nodes
#If no IP is found, this implies that a new cluster needs to be created,
#in order to do that you need to bootstrap this node
wsrep_cluster_address=gcomm://10.0.0.7,10.0.0.38,10.0.0.48
# In order for Galera to work correctly binlog format should be ROW
binlog_format=ROW
# MyISAM storage engine has only experimental support
default_storage_engine=InnoDB
# Slave thread to use
wsrep_slave_threads= 8
wsrep_log_conflicts
# This changes how InnoDB autoincrement locks are managed and is a requirement for Galera
innodb_autoinc_lock_mode=2
# Node IP address
wsrep_node_address=10.0.0.7
# Cluster name
wsrep_cluster_name=pxc-cluster
#If wsrep_node_name is not specified, then system hostname will be used
wsrep_node_name=pxc-cluster-node-1
#pxc_strict_mode allowed values: DISABLED,PERMISSIVE,ENFORCING,MASTER
pxc_strict_mode=ENFORCING
# SST method
wsrep_sst_method=xtrabackup-v2
#Authentication for SST method
wsrep_sst_auth="sstuser:s3cretPass"
systemctl start [email protected] #第一台启动命令是不同的
ss -ntl
cat /var/log/mysqld.log | grep password
mysql -uroot -pdxnBiywtC9+A
alter user 'root'@'localhost' identified by '123456';
mysql> create user 'sstuser'@'localhost' identified by 's3cretPass';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT on *.* to'sstuser'@'localhost';
mysql> SHOW VARIABLES LIKE 'wsrep%'\G;
SHOW STATUS LIKE 'wsrep%'\G;
Variable_name: wsrep_cluster_size
Value: 4
10.0.0.38
yum -y install Percona-XtraDB-Cluster-57
[root@localhost yum.repos.d]#vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
wsrep_node_address=10.0.0.38 #主要是ip地址和节点名称需要修改,其他和10.0.0.7配置相同
wsrep_node_name=pxc-cluster-node-2
systemctl start mysql
10.0.0.48 与10.0.0.38配置相似
10.0.0.47要加入集群
添加自己的IP地址及修改IP和节点名称,其他与10.0.0.7一致
[root@localhost ~]#vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
wsrep_cluster_address=gcomm://10.0.0.7,10.0.0.38,10.0.0.48,10.0.0.47
[root@localhost ~]#systemctl start mysql
29. 总结mysql配置最佳实践。
基础规范
1.必须使用InnoDB存储引擎
2.使用UTF8MB4字符集
3.数据表、数据字段必须加入中文注释
4.禁止使用存储过程、视图、触发器、Event
5.禁止存储大文件或大照片
命名规范
6.只允许使用内网域名,而不是IP连接数据库
7.线上环境、开发环境、测试环境数据库内网域名遵循命名规范
8.库名、表名、字段名:小写,下划线风格,不超过32个字符,必须见名知意
9.库名与应用名称尽量一致
表设计规范
10.单实例表数目必须小于500
11.单表列数目必须小于30
12.表必须有主键
13.禁止使用外键,如果有外键完整性约束,需要应用程序控制
字段设计规范
14.必须把字段定义为NOT NULL并且提供默认值
15.禁止使用TEXT、BLOB类型
16.禁止使用小数存储货币
17.必须使用varchar(20)存储手机号
18.禁止使用ENUM,可使用TINYINT代替
索引设计规范
19.单表索引建议在五个以内
20.单索引字段数不允许超过5个
21.禁止在更新十分频繁、区分度不高的属性建立索引
22.建立组合索引、必须把区分度高的字段放在前面
SQL使用规范
23.禁止使用SELECT*,只要获取必要的字段,需要显示说明列属性
30. 总结openvpn原理,并完成1键安装不同版本vpn脚本,可以适配rocky, ubuntu, centos主机。同时支持添加账号,注销账号。
openvpn原理
VPN: Virual Private Network ,虚拟私有网络,或称为虚拟专用网络,常用于在公用网络上建立专用网络,进行加密通讯,VPN网关通过对数据包的加密和数据包目标地址的转换实现远程访问。
OpenVPN是一个基于OpenSSL库的应用层VPN实现。OpenVPN允许参与建立VPN的单点使用共享密钥,电子证书,或者用户名/密码进行身份验证。
虚拟网卡
在Linux2.4版本以上,操作系统支持一个名为tun的设备,tun设备的驱动程序中包含两个部分,一部分是字符设备驱动,一部分是网卡驱动。网卡的驱动把从TCP/IP协议栈收到的数据包结构skb放于tun设备的读取队列,用户进程通过调用字符设备接口read获得完整的IP数据包,字符驱动read函数的功能是从设备的读取队列读取数据,将核心态的skb传递给用户;反过来字符驱动write函数给用户提供了把用户态的数据写入核心态的接口,write函数把用户数据写入核心空间并穿入TCP/IP协议栈。该设备既能以字符设备的方式被读写,作为系统的虚拟网卡,也具有和物理网卡相同的特点:能够配置IP地址和路由。对虚拟网卡的使用是OpenVPN实现其SSL VPN功能的关键。
地址池以及路由
OpenVPN服务器一般需要配置一个虚拟IP地址池和一个自用的静态虚拟IP地址(静态地址和地址池必须在同一个子网中),然后为每一个成功建立SSL连接的客户端动态分配一个虚拟IP地址池中未分配的地址。这样,物理网络中的客户端和OpenVPN服务器就连接成一个虚拟网络上的星型结构局域网,OpenVPN服务器成为每个客户端在虚拟网络上的网关。OpenVPN服务器同时提供对客户端虚拟网卡的路由管理。当客户端对OpenVPN服务器后端的应用服务器的任何访问时,数据包都会经过路由流经虚拟网卡,OpenVPN程序在虚拟网卡上截获数据IP报文,然后使用SSL协议将这些IP报文封装起来,再经过物理网卡发送出去。OpenVPN的服务器和客户端在虚拟网卡之上建立起一个虚拟的局域网络,这个虚拟的局域网对系统的用户来说是透明的。
客户端与服务端安全连接的建立
OpenVPN的服务器和客户端支持tcp和udp两种连接方式,只需在服务端和客户端预先定义好使用的连接方式(tcp或udp)和端口号,客户端和服务端在这个连接的基础上进行SSL握手。连接过程包括SSL的握手以及虚拟网络上的管理信息,OpenVPN将虚拟网上的网段、地址、路由发送给客户端。连接成功后,客户端和服务端建立起SSL安全连接,客户端和服务端的数据都流入虚拟网卡做SSL的处理,再在tcp或udp的连接上从物理网卡发送出去。
数据包的处理过程
发送数据流程
应用层的外出数据,经过系统调用接口传入核心TCP/IP层做处理,在TCP/IP经过路由到虚拟网卡,虚拟网卡的网卡驱动发送处理程序hard_start_xmit()将数据包加入skb表并完成数据包从核心区到用户区的复制,OpenVPN调用虚拟网卡的字符处理程序tun_read(),读取到设备上的数据包,对读取的数据包使用SSL协议做封装处理后,通过socket系统调用发送出去。
接受数据流程
物理网卡接收数据包,经过核心TCP/IP上传到OpenVPN,OpenVPN通过link_socket_read()接收数据包,使用SSL协议进行解包处理,经过处理的数据包OpenVPN调用虚拟网卡的字符处理程序tun_write()写入虚拟网卡的字符设备,设备驱动程序完成数据从用户区到核心区的复制,并将数据写入skb链表,然后调用网卡netif_rx()接收程序,数据包再次进入系统TCP/IP协议栈,传到上层应用程序。如图1所示。
数据包的封装
OpenVPN提供tun和tap两种工作模式。在tun模式下,从虚拟网卡上收到的是不含物理帧头IP数据包,SSL处理模块对IP包进行SSL封装;在tap模式下,从虚拟网卡上收到的是包含物理帧头的数据包,SSL处理模块对整个物理帧进行SSL封装。Tap模式称为网桥模式,整个虚拟的网络就像网桥方式连接的物理网络。这种模式可以传输以太网帧、IPX、NETBIOS等数据包,应用范围更广。
OpenVPN与Openssl
OpenVPN软件包需要和openssl软件一起安装,因为OpenVPN调用了Openssl函数库,OpenVPN的客户端和服务端建立SSL链接的过程是通过调用Openssl来实现的。通过bio_write()/函数把数据写入Openssl的状态机通道,bio_read()从Openssl读取结果。OpenVPN还调用Openssl的加解密函数处理转发的数据包。
小结
OpenVPN是一款基于SSL的开源VPN软件,它实现了利用SSL来保证网络通讯安全性的目的,同时避免了传统SSL VPN仅提供简单的Web应用的不足,它具有支持各种应用协议,支持Windows,Linux,BSD,MAC OS等多平台的特点。在上面的应用系统中,通过对OpenVPN的灵活部署,实现了五种访问形式。其中部门内用户点到点通信、用户跨部门访问应用服务器、用户跨部门点到点通信、数据包在客户端到SSL VPN服务器以及SSL VPN服务器间接力传送;跨部门的应用服务器数据通信时,SSL VPN服务器要做内网数据向外网转发的反向代理,而这些应用需求在传统SSL代理服务器中是比较难实现的。
脚本实现
#!/bin/bash
install_openvpn () {
. /etc/os-release
if [ $ID = "rocky" -o $ID = "centos" ];then
echo OS version is rocky or centos
yum -y install openvpn
yum -y install easy-rsa
cp /usr/share/doc/openvpn/sample/sample-config-files/server.conf /etc/openvpn
cp -r /usr/share/easy-rsa/ /etc/openvpn/server
cp /usr/share/doc/easy-rsa/vars.example /etc/openvpn/server/easy-rsa/3
cd /etc/openvpn/server/easy-rsa/3
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa gen-req server nopass
./easyrsa sign server server <<EOF
yes
EOF
./easyrsa gen-dh
cp -a /usr/share/easy-rsa/ /etc/openvpn/client
cd /etc/openvpn/client/easy-rsa/3
cp /usr/share/doc/easy-rsa/vars.example /etc/openvpn/client/easy-rsa/3/vars
./easyrsa init-pki
elif [ $ID = "ubuntu" ];then
echo OS version is Ubuntu
apt update
apt -y install openvpn
apt -y install easy-rsa
cp /usr/share/doc/openvpn/sample/sample-config-files/server.conf /etc/openvpn
cp -r /usr/share/easy-rsa/ /etc/openvpn/server
cp /usr/share/doc/easy-rsa/vars.example /etc/openvpn/server/easy-rsa/3
cd /etc/openvpn/server/easy-rsa/3
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa gen-req server nopass
./easyrsa sign server server <<EOF
yes
EOF
./easyrsa gen-dh
cp -a /usr/share/easy-rsa/ /etc/openvpn/client
cd /etc/openvpn/client/easy-rsa/3
cp /usr/share/doc/easy-rsa/vars.example /etc/openvpn/client/easy-rsa/3/vars
./easyrsa init-pki
else
echo "不支持OS"
exit
fi
}
useradd () {
read -p "请输入创建用户姓名的拼音(例如:libai):" NAME
cd /etc/openvpn/client/easy-rsa/3
./easyrsa gen-req ${NAME} nopass <<EOF
EOF
./easyrsa import-req /data/openvpn/easy-rsa/pki/reqs/${NAME}.req ${NAME}
./easyrsa sign client ${NAME} <<EOF
yes
EOF
}
userdel () {
read -p "请输入删除用户姓名的拼音(例如:libai):" NAME
/etc/openvpn/client/easy-rsa/3
./easyrsa revoke ${NAME} <<EOF
yes
EOF
./easyrsa gen-crl
systemctl restart [email protected]
}
echo -en "\E[$[RANDOM%7+31];1m"
cat <<EOF
请选择:
1)安装openvpn
2)创建用户
3)删除用户
4)选择结束
EOF
echo -en '\E[0m'
read -p "请输入上面数字1-5: " MENU
case $MENU in
1)
echo "正在安装openvpn"
install_openvpn
;;
2)
echo "正在创建用户"
useradd
;;
3)
echo "正在删除用户"
userdel
;;
4)
echo "选择结束"
break
;;
*)
echo "INPUT FALSE!"
esac