分类 数据库 下的文章

MHA

原理

avatar
MHA是一套mysql高可用方案,在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且 在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。 MHA里有 两个角色一个是MHA Node(数据节点)另一个是MHA Manager(管理节点)。 MHA Manager可以单独部署 在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。MHA Node运行在每台 MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新 数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完 全透明。

工作流程

  • 把宕机的master二进制日志保存下来
  • 找到binlog位置点最新的slave
  • 用这个slave的relay log来修复其他的slave
  • 把宕机的master上保存下的二进制日志恢复到其他最新位置点的slave上
  • 把含有最新位置点的slave提拔为新的master
  • 把其他slave指向新的master

MHA软件的包括manager和node两个工具包

manager

Manager工具包主要包括以下几个工具:
masterha_check_ssh              检查MHA的SSH配置状况
masterha_check_repl             检查MySQL复制状况
masterha_manger                 启动MHA
masterha_check_status           检测当前MHA运行状态
masterha_master_monitor       检测master是否宕机
masterha_master_switch          控制故障转移(自动或者手动)
masterha_conf_host               添加或删除配置的server信息

node

save_binary_logs        保存和复制master的二进制日志
apply_diff_relay_logs   识别差异的中继日志事件并将其差异的事件应用于其他的slave
purge_relay_logs        清除中继日志(不会阻塞SQL线程)

配置

现准备四台机器,一台server做manager,21为主,22,23为从,其中22为候选,在21宕机的时候成为新的master

mha需要通过ssh来交互,所以要先创建ssh免密登录环境

manager和三台机子,三台机子之间互相

ssh-keygen
ssh-copy-id 192.168.226.149
ssh-copy-id 192.168.226.152
ssh-copy-id 192.168.226.153

在21,22,23上面先搭建一主两从

vim /etc/yum.repos.d/mariadb.repo
[mariadb]
name=MariaDB
baseurl=http://mirrors.ustc.edu.cn/mariadb/yum/10.2/centos7-amd64/
gpgkey=http://mirrors.ustc.edu.cn/mariadb/yum/RPM-GPG-KEY-MariaDB
gpgcheck=1

yum install -y mariadb-server.x86_64

yum -y install mha4mysql-node-0.56-0.el6.noarch.rpm

systemctl start mysql
mysql_secure_installation #密码此处设置为mariadb123456

mysql -uroot -pmariadb123456
#在21,22上安装插件,开启半同步复制
install plugin rpl_semi_sync_master soname 'semisync_master.so';
install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
set global rpl_semi_sync_master_enabled = 1;
set global rpl_semi_sync_slave_enabled = 1;
grant replication slave on *.* to 'repluser'@'192.168.226.%' identified by 'repluser123456';
flush privileges;

在23上只开启同步
install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
set global rpl_semi_sync_slave_enabled = 1;

修改三台机器配置

# MariaDB-21配置文件
cat /etc/my.cnf.d/server.cnf
[mysqld]
skip_name_resolve = ON
innodb_file_per_table = ON
server-id = 21
log-bin = master-bin
relay_log_purge = 0
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 3000
rpl_semi_sync_slave_enabled = 1
 
# MariaDB-22配置文件
cat /etc/my.cnf.d/server.cnf
[mysqld]
skip_name_resolve = ON
innodb_file_per_table = ON
server-id = 22
log-bin = master-bin
relay_log_purge = 0
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 3000
rpl_semi_sync_slave_enabled = 1
 
# MariaDB-23配置文件
cat /etc/my.cnf.d/server.cnf
[mysqld]
skip_name_resolve = ON
innodb_file_per_table = ON
server-id = 23
log-bin = master-bin
relay_log_purge = 0
rpl_semi_sync_slave_enabled = 1

重启服务,加载配置文件,配置主从同步

[root@21 ~]# systemctl restart mariadb.service
[root@21 ~]# mysql -uroot -pmariadb123456
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 9
Server version: 10.2.43-MariaDB-log 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 master status\G;
*************************** 1. row ***************************
            File: master-bin.000001
        Position: 329
    Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)

ERROR: No query specified

#在22,23上配置主从同步
MariaDB [(none)]> show master status\G;
*************************** 1. row ***************************
            File: master-bin.000001
        Position: 329
    Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)


change master to master_host='192.168.226.149',master_user='repluser',master_password='repluser123456',master_log_file='master-bin.000001',master_log_pos=329;


MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.226.149
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 329
               Relay_Log_File: server5-relay-bin.000002
                Relay_Log_Pos: 556
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

在21上授权manager用户管理mha各节点,两台slave会同步这个用户

MariaDB [(none)]> grant all on *.* to 'mhauser'@'192.168.226.%' identified by 'mhauser123456';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

配置mha-manager

yum install -y epel-release.noarch
yum -y install mha4mysql-manager-0.56-0.el6.noarch.rpm \
mha4mysql-node-0.56-0.el6.noarch.rpm

mkdir /etc/mha
cat /etc/mha/app1.conf
[server default]
user=mhauser
password=mhauser123456
ssh_user=root
master_binlog_dir=/var/lib/mysql
remote_workdir=/data/log/masterha
manager_workdir=/usr/local/mha
manager_log=/usr/local/mha/manager.log
 
ping_interval=1
repl_user=repluser
repl_password=repluser123456
 
[server1]
hostname=192.168.226.149
candidate_master=1
 
[server2]
hostname=192.168.226.152
candidate_master=1
 
[server3]
hostname=192.168.226.153
no_master=1
 
# ssh检测,授权检测,启动MHA
chmod +x /etc/mha/app1.conf
mkdir /usr/local/mha
 
masterha_check_ssh --conf=/etc/mha/app1.conf
masterha_check_repl --conf=/etc/mha/app1.conf
masterha_manager --conf=/etc/mha/app1.conf  2>&1 &
masterha_check_status --conf=/etc/mha/app1.conf

app1 (pid:17140) is running(0:PING_OK), master:192.168.226.149

验证

21创库
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

MariaDB [(none)]> create database db1;
Query OK, 1 row affected (0.00 sec)

22同步
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| db1                |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)

22创库

MariaDB [(none)]> create database db2;
Query OK, 1 row affected (3.01 sec)

23不同步
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| db1                |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)


21关机
[root@21 ~]# mysqladmin -uroot -pmariadb123456  "shutdown"

22建库
MariaDB [(none)]> create database db3;
Query OK, 1 row affected (0.00 sec)

23同步,可见22已变成新的主
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| db1                |
| db3                |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
5 rows in set (0.00 sec)

切换复原

先让21指向22

MariaDB [(none)]> change master to master_host='192.168.226.152',master_user='repluser',master_password='repluser123456',master_log_file='master-bin.000001',master_log_pos=583;
Query OK, 0 rows affected (0.01 sec)

MariaDB [(none)]> start slave;

再在mha拉起
masterha_master_switch --conf=/etc/mha/app1.conf --master_state=alive --new_master_host=10.0.0.21 --new_master_port=3306 --orig_master_is_new_slave

再在mha手动切换

MySQL调优

  1. 采用合适的存储引擎
  2. 高可用框架
  3. 创建阶段选择更合适的变量种类,如使用日期时间类型而不是字符串来保存时间,用枚举来代替字符串
  4. 适当把一些大而不常访问的字段拆分到别的表里面
  5. 开启缓存
  6. 建立合适的索引
  7. 优化查询语句,如count(*)-->count(某一列),关联查询访问建有索引的列
  8. 避免冗余和重复的索引,比如有一个索引(A,B),再创建索引(A)就是冗余索引
  9. 建立合适的视图,保障数据安全性,提高查询效率

基础概念

基本操作见我的此篇博客Mysql

关系型数据课和非关系型数据库

关系型数据库:以多张二维表及他们之间的关系所组成

优点:

  • 易于维护,结构一致
  • sql语言通用,使用方便
  • 支持单表和多表之间的复杂查询

缺点:

  • 读写性能较差
  • 固定表结构,灵活度稍欠
  • 高并发读写需求对硬盘i/o造成很大罚单

非关系型数据库:以键值对(或者文档、图形等)来存储数据

优点:

  • 基于键值对,数据间没有耦合性,可扩展性好
  • 不需要sql层的解析,性能高

mysql常用参数:

-u:用户

-host:主机

-p:密码

--port:端口

-D:登录指定的数据库

工作流程

一个mysql进程实例=mysql后台守护进程+master 线程+worker 线程+预分配的内存.一台机子上可以启动多个mysql进程

连接方式

TCP/IP(远程)
mysql -uroot -pxxx -h 192.168.226.148 -P3306

socket
mysql -u -p -S /emp/mysql.sock

avatar
avatar

上层服务通过连接池组件来连接mysql。

  • 提供连接协议:TCP/IP 、SOCKET
  • 提供验证:用户、密码,IP,SOCKET
  • 提供专用连接线程:接收用户SQL,返回结果

第二层包含mysql大部分核心服务,如查询分析优化缓存内置函数等,所有跨存储引擎功能都在这一层实现,如存储过程触发器视图等。

  • 接收上层传送的SQL语句
  • 语法验证模块:验证语句语法,是否满足SQL_MODE
  • 语义检查:判断SQL语句的类型

    • DDL :数据定义语言
    • DCL :数据控制语言
    • DML :数据操作语言
    • DQL: 数据查询语言
  • 权限检查:用户对库表有没有权限
  • 解析器:对语句执行前,进行预处理,生成解析树(执行计划),说白了就是生成多种执行方案
  • 优化器:根据解析器得出的多种执行计划,进行判断,选择最优的执行计划。代价模型:资源(CPU IO MEM)的耗损评估性能好坏
  • 执行器:根据最优执行计划,执行SQL语句,产生执行结果
  • 提供查询缓存(默认是没开启的),会使用redis tair替代查询缓存功能
  • 提供日志记录(日志管理章节):binlog,默认是没开启的。

第三层是存储引擎,存储引擎负责mysql数据的存储和提取,服务器通过API和存储引擎进行通信。这些接口屏蔽了不同存储引擎之间的差异,使得这些差异对上层的查询过程透明化,但存储引擎一般不会去解析sql,不同存储引擎之间不会互相通信,只是简单的响应上层服务器的请求。mysql采用插件式结构的存储引擎,可以根据场景来选择不同的引擎,引擎对于上层应用程序和底层的文件系统都是透明的。

  • 负责根据SQL层执行的结果,从磁盘上拿数据
  • 将16进制的磁盘数据,交由SQL结构化化成表
  • 连接层的专用线程返回给用户

第四层是文件系统,所有数据和日志最终以文件的形式存储在硬盘上

数据库:物理操作系统文件或者其他形式文件类型的集合

数据库实例:由数据库后台进程线程以及一个共享内存区组成,数据库实例才是真正用来操作数据库文件的,也即是说,数据库是由一个个文件组成的,而当要对这些文件执行select等操作的时候,就得要通过数据库实例来完成对数据库的操作

mysql区别于别的数据库最大的特点就是插件式的表存储引擎,这个插件式存储引擎架构提供了一系列标准的管理和服务,这些标准和存储引擎本身无关,是数据库系统本身所需,如sql分析器优化器等,而存储引擎是底层物理结构的实现。存储引擎是基于表的,而不是数据库

引擎

存储引擎的功能

  • 数据读写
  • 数据安全
  • 提高性能
  • 热备份
  • 自动故障恢复
  • 高可用方面支持

https://blog.csdn.net/qq_35642036/article/details/82820178

InnoDB与MyISAM的区别

  • innodb支持事务,对于每一条sql语言都默认封装成事务,自动提交,影响速度,所以最好把多条sql语言组成一个事务;;;;myisam不支持事务
  • innodb支持外键,myisam不支持。对于包含外键的innodb表转为myisam会失败
  • innodb是聚集索引,使用B+树作为索引结构,数据文件和(主键)索引绑在一起,所以必须要又主键,通过主键所以效率很高。但是辅助索引需要两次查询,先查询到主键,再通过主键查询到数据,因此主键不应该太大,不然其他索引也会很大
  • myisam是非聚集索引,也使用B+树作为索引结构,索引和数据分离,索引保存的是数据文件的指针,主键索引和辅助索引相互独立
  • innodb不保存表的行数,在执行select count(*) from table时候需要扫描全表,因为innodb的事务特性,在同一时刻表的行数对于不同的事务是不一样的,innodb会去尝试遍历一个尽可能小的索引。myisam用一个变量保存了整个表的行数,执行时只需要读出该变量
  • innodb支持表、行级锁(默认),innodb的锁是是现在索引上的,而不是锁在物理行立即上,如果访问没有命中索引,无法使用行锁,而是退化成表锁。myisam支持表级锁
  • myisam表格可以被压缩后进行查询操作
  • innodb必须要有唯一索引,如果用户没有指定会自己找一个隐藏列来充当默认主键,myisam可以没有
  • Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI

      Innodb:frm是表定义文件,ibd是数据文件
    
      Myisam:frm是表定义文件,myd是数据文件,myi是索引文件
    

InnoDB为什么推荐使用自增ID作为主键?

答:自增ID可以保证每次插入时B+索引是从右边扩展的,可以避免B+树和频繁合并和分裂(对比使用UUID)。如果使用字符串主键和随机主键,会使得数据随机插入,效率比较差。


innodb引擎的4大特性

   插入缓冲(insert buffer),二次写(double write),自适应哈希索引(ahi),预读(read ahead)
MariaDB [(none)]> show engines\G;
*************************** 1. row ***************************
      Engine: InnoDB
     Support: DEFAULT
     Comment: Percona-XtraDB, Supports transactions, row-level locking, and foreign keys
Transactions: YES
          XA: YES
  Savepoints: YES
*************************** 2. row ***************************
      Engine: MRG_MYISAM
     Support: YES
     Comment: Collection of identical MyISAM tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 3. row ***************************
      Engine: MyISAM
     Support: YES
     Comment: Non-transactional engine with good performance and small data footprint
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 4. row ***************************
      Engine: BLACKHOLE
     Support: YES
     Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 5. row ***************************
      Engine: PERFORMANCE_SCHEMA
     Support: YES
     Comment: Performance Schema
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 6. row ***************************
      Engine: CSV
     Support: YES
     Comment: Stores tables as CSV files
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 7. row ***************************
      Engine: ARCHIVE
     Support: YES
     Comment: gzip-compresses tables for a low storage footprint
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 8. row ***************************
      Engine: MEMORY
     Support: YES
     Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 9. row ***************************
      Engine: FEDERATED
     Support: YES
     Comment: Allows to access tables on other MariaDB servers, supports transactions and more
Transactions: YES
          XA: NO
  Savepoints: YES
*************************** 10. row ***************************
      Engine: Aria
     Support: YES
     Comment: Crash-safe tables with MyISAM heritage
Transactions: NO
          XA: NO
  Savepoints: NO
10 rows in set (0.00 sec)

索引

https://blog.csdn.net/guanyasu/article/details/53443142

索引的作用是加速查找,主键\unique\联合唯一\联合主键\index\联合index都是索引

当表中已有大量数据时,建立索引会占用大量磁盘空间且速度很慢,但是等建完后查询会变快

常用索引

普通索引INDEX:加速查找 
唯一索引: 
-主键索引PRIMARY KEY:加速查找+约束(不为空、不能重复) 
-唯一索引UNIQUE:加速查找+约束(不能重复) 
联合索引: 
-PRIMARY KEY(id,name):联合主键索引 
-UNIQUE(id,name):联合唯一索引 
-INDEX(id,name):联合普通索引

创建方式

CREATE INDEX indexName ON table_name (column_name)创建

ALTER table tableName ADD INDEX indexName(columnName)修改

CREATE TABLE mytable(  
 
ID INT NOT NULL,   
 
username VARCHAR(16) NOT NULL,  
 
INDEX [indexName] (username(length))  
 
);  创建表时

DROP INDEX [indexName] ON mytable; 删除

CREATE UNIQUE INDEX indexName ON mytable(username(length)) 唯一索引

索引分类:B+树索引,hash索引

对比

MariaDB [db2]> select count(*) from s1;
+----------+
| count(*) |
+----------+
|  2999999 |
+----------+
1 row in set (2.02 sec)

MariaDB [db2]> create index a on s1(id);
Query OK, 0 rows affected (11.52 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [db2]> select count(*) from s1;
+----------+
| count(*) |
+----------+
|  2999999 |
+----------+
1 row in set (1.23 sec)

b+树

avatar
b+树数据全存在叶子节点,非叶子节点只放指向这些元素记录的指针(索引),父节点跟子节点重复的元素是这个子节点当中最大的元素,叶子节点的元素按从小到大的顺序依次排列,且互相之间有指针连在一起
b+树漫画,小仓鼠还挺可爱的

sql模型

ANSI QUOTES::宽松模式,对插入数据进行校验,如果不符合定义类型或长度,对数据类型调
整或截断保存,报warning警告。 双引号相当于反引号,只可以引用表名等字段名称,字符串只可
以使用单引号引用;
IGNORE_SPACE:在内建函数中忽略多余的空白字符;
STRICT_ALL_TABLES:如果没有设置这个值,非法的数据都允许存入,但是会有一个警告提示。如
果设置了,所有非法的数据都不允许填入,并且返回一个错误;
STRICT_TRANS_TABLES:向一个支持事务的表中插入非法数据的时候不允许,并且返回一个错
误;
TRADITIONAL:严格模式,当向mysql数据库插入数据时,进行数据的严格校验,保证错误数据不
能插入,报error错误。用于事物时,会进行事物的回滚


SELECT @@[GLOBAL | SESSION].sql_mode; 显示值 
set GLOBAL | SESSION sql_mode=[值]; 修改值

事务

innodb引擎支持事务,事务保证一批sql语句要么全部执行,要么全部不执行(回滚),把数据库从一种一致性转换为另外一种一致性,来保证数据库的完整性.事务一般针对update,delete,insert

ACID

事务必须满足ACID特性:

  • A:原子性,事务必须是执行任务的最小单位,事务要么成功要么撤回
  • C:一致性,把数据库从一种一致性转换为另外一种一致性
  • I:隔离性:每个事务之间是隔离的
  • D:持久性:事务一旦执行,数据的修改是永久的

隔离等级

read uncommitted(未提交读):允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
read conmitted (提交读):允许读取并发事务已经提交的数据,能够解决脏读
repeatable read (可重读):对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,能够解决不可重复读、脏读现象
serializable(可串行化读):事务需要按串行化解决(MVCC)

格式

一个事务只能由commit(提交)或者rollback(回滚)结束,事务在执行过程中不是真的对数据进行了修改,在提交之前都是暂存于内存当中.当一个事务开启时,如果再开启另外一个事务,那么那个新开的事务会被卡住

begin;#开始
操作

commit/rollback

日志

错误日志log_error

存放数据库启动\关闭\日常中的状态信息错误警告等

MariaDB [db2]> show variables like "%log_error%";
+---------------+------------------------------+
| Variable_name | Value                        |
+---------------+------------------------------+
| log_error     | /var/log/mariadb/mariadb.log |
+---------------+------------------------------+
1 row in set (0.01 sec)

二进制日志binlog

备份、主从都依赖二进制日志,binlog位于sql层,记录变更数据的sql语句,不记录查询语句

二进制日志默认关闭,需要去配置文件手动开启

vim /etc/my.cnf 
server_id=6 # 设置id 
log_bin=mysql-bin # 开启并指定二进制日志目录及前缀名,记得关selinux 
binlog_format=row # binlog 的日志记录格式

日志记录格式

SBR:可读性较高,日志量少,但是不够严谨
ROW:可读性很低,日志量大,足够严谨

event事件:二进制日志的最小记录单元

对于DDL(数据库定义语言,create等),DCL(数据库控制语言,grant等),一个语句就是一个event,对于DML(数据操纵,insert等),只记录已提交的事务

查看日志开启情况

MariaDB [(none)]> show variables like '%log_bin%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| log_bin                         | ON    |
| log_bin_trust_function_creators | OFF   |
| sql_log_bin                     | ON    |
+---------------------------------+-------+

查看二进制文件数量

MariaDB [(none)]> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       245 |
+------------------+-----------+
1 row in set (0.00 sec)

MariaDB [(none)]> flush logs;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       288 |
| mysql-bin.000002 |       245 |
+------------------+-----------+
2 rows in set (0.00 sec)

查看正在使用的二进制文件

MariaDB [(none)]> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000002 |      245 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.01 sec)

查看日志内容

MariaDB [(none)]> show binlog events in 'mysql-bin.000002';
+------------------+-----+-------------+-----------+-------------+-------------------------------------------+
| Log_name         | Pos | Event_type  | Server_id | End_log_pos | Info                                      |
+------------------+-----+-------------+-----------+-------------+-------------------------------------------+
| mysql-bin.000002 |   4 | Format_desc |         6 |         245 | Server ver: 5.5.68-MariaDB, Binlog ver: 4 |
+------------------+-----+-------------+-----------+-------------+-------------------------------------------+
1 row in set (0.00 sec)

详细查看日志内容

[root@server1 ~]# mysqlbinlog --base64-output=decode-rows -vvv /data/binlog/mysql-bin.000002

基于position进行日志截取

mysqlbinlog --start-position=219 --stop-position=1347 /data/binlog/mysql-bin.000003 >/tmp/bin.sql

使用二进制日志进行数据恢复

创建一个库表,往里面放点数据
MariaDB [db1]> show binlog events in 'mysql-bin.000002';
+------------------+-----+-------------+-----------+-------------+-------------------------------------------+
| Log_name         | Pos | Event_type  | Server_id | End_log_pos | Info                                      |
+------------------+-----+-------------+-----------+-------------+-------------------------------------------+
| mysql-bin.000002 |   4 | Format_desc |         6 |         245 | Server ver: 5.5.68-MariaDB, Binlog ver: 4 |
| mysql-bin.000002 | 245 | Query       |         6 |         326 | create database db1                       |
| mysql-bin.000002 | 326 | Query       |         6 |         412 | use `db1`; create table tb1(id int)       |
| mysql-bin.000002 | 412 | Query       |         6 |         479 | BEGIN                                     |
| mysql-bin.000002 | 479 | Table_map   |         6 |         520 | table_id: 33 (db1.tb1)                    |
| mysql-bin.000002 | 520 | Write_rows  |         6 |         564 | table_id: 33 flags: STMT_END_F            |
| mysql-bin.000002 | 564 | Xid         |         6 |         591 | COMMIT /* xid=18 */                       |
+------------------+-----+-------------+-----------+-------------+-------------------------------------------+
7 rows in set (0.00 sec)

MariaDB [db1]> select * from tb1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
MariaDB [db1]> drop database db1;# 模拟故障
Query OK, 1 row affected (0.01 sec)

MariaDB [(none)]> show master status; #查看正在使用的二进制日志
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000002 |      670 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

MariaDB [(none)]> show binlog events in 'mysql-bin.000002';
+------------------+-----+-------------+-----------+-------------+-------------------------------------------+
| Log_name         | Pos | Event_type  | Server_id | End_log_pos | Info                                      |
+------------------+-----+-------------+-----------+-------------+-------------------------------------------+
| mysql-bin.000002 |   4 | Format_desc |         6 |         245 | Server ver: 5.5.68-MariaDB, Binlog ver: 4 |
| mysql-bin.000002 | 245 | Query       |         6 |         326 | create database db1                       |
| mysql-bin.000002 | 326 | Query       |         6 |         412 | use `db1`; create table tb1(id int)       |
| mysql-bin.000002 | 412 | Query       |         6 |         479 | BEGIN                                     |
| mysql-bin.000002 | 479 | Table_map   |         6 |         520 | table_id: 33 (db1.tb1)                    |
| mysql-bin.000002 | 520 | Write_rows  |         6 |         564 | table_id: 33 flags: STMT_END_F            |
| mysql-bin.000002 | 564 | Xid         |         6 |         591 | COMMIT /* xid=18 */                       |
| mysql-bin.000002 | 591 | Query       |         6 |         670 | drop database db1                         |
+------------------+-----+-------------+-----------+-------------+-------------------------------------------+
8 rows in set (0.00 sec)

[root@server1 ~]# mysqlbinlog --start-position=245 --stop-position=591 /var/lib/mysql/mysql-bin.000002  > /tmp/bin2.sql
[root@server1 ~]# ll /tmp/bin2.sql
-rw-r--r--. 1 root root 2265 3月  12 11:03 /tmp/bin2.sql

MariaDB [(none)]> set sql_log_bin=0;#暂时关闭记录
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> source /tmp/bin2.sql;
Query OK, 0 rows affected (0.00 sec)
MariaDB [db1]> set sql_log_bin = 1;
Query OK, 0 rows affected (0.00 sec)MariaDB [db1]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db1                |
| mysql              |
| performance_schema |
+--------------------+

慢日志slow_log

记录比较慢的sql语句,默认关闭,需要通过修改配置文件来开启

[root@server1 ~]# vim /etc/my.cnf

slow_query_log=1
slow_query_log_file = /var/log/mariadb/slow.log
long_query_time=0.1
log_queries_not_using_indexes

[root@server1 ~]# systemctl restart mariadb.service
MariaDB [(none)]> show variables like "%slow%";
+---------------------+--------------------------------------------------------------------------------------------------------------+
| Variable_name       | Value                                                                                                        |
+---------------------+--------------------------------------------------------------------------------------------------------------+
| log_slow_filter     | admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk |
| log_slow_queries    | ON                                                                                                           |
| log_slow_rate_limit | 1                                                                                                            |
| log_slow_verbosity  |                                                                                                              |
| slow_launch_time    | 2                                                                                                            |
| slow_query_log      | ON                                                                                                           |
| slow_query_log_file | /var/log/mariadb/slow.log                                                                                    |
+---------------------+--------------------------------------------------------------------------------------------------------------+

主从复制

avatar
主服务器上的更新操作会被写入二进制文件中,从服务器用io线程去读主的二进制日志,然后写道relaylog里,sql线程会去执行relaylog。而对从服务器操作不会对主造成影响

主从的三种模式:https://zhuanlan.zhihu.com/p/307288925

https://zhuanlan.zhihu.com/p/521863168

实验

两台机器,一主一从

vim /etc/my.conf

server_id=1
log_bin=mysql-bin
binlog_format=row

重启服务

#创建主从复制用户
MariaDB [(none)]> grant replication slave on *.* to rep@'192.168.226.%' identified by '123';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |     2971 |              |                  |
+------------------+----------+--------------+------------------+

vim /etc/my.cnf
server_id =2 #不能和主一样

systemctl restart mariadb.service 12345

MariaDB [(none)]> change master to master_host='192.168.226.148',master_port=3306,master_user='rep',master_password='123',master_log_file='mysql-bin.000003',master_log_pos=2971;

MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.226.148
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 2971
               Relay_Log_File: mariadb-relay-bin.000002
                Relay_Log_Pos: 529
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 2971
              Relay_Log_Space: 825
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
1 row in set (0.00 sec)

ERROR: No query specified

验证

从
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)
主
MariaDB [(none)]> create database db1;
Query OK, 1 row affected (0.01 sec)

从
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db1                |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)

备份

备份分类

按照备份数据位置分类
  热备:硬盘以及内存中的⼀些数据进⾏备份
  冷备:数据库硬盘中的数据
按照备份后⽂件的内容
  逻辑备份:⼀般内容分是sql语句
  裸⽂件备份:拷⻉数据库的物理文件,⼀般内容是⼆进制数据
按照备份数据的内容
  完全备份:对数据库进⾏⼀个完整的备份
  增量备份:在上次的完全备份基础上对更新的数据进⾏备份
  ⽇志备份:⼆进制⽇志备份-->当数据库宕机之后进⾏数据恢复的依据

冷备份的优点:
  备份简单,只要拷⻉相关⽂件即可
  易于跨平台
  恢复简单,只要把⽂件恢复到相关位置即可
  恢复速度快,不需要执⾏任何sql语句,也不需要重新建索引
冷备份缺点
  冷备⽂件通常⽐逻辑⽂件⼤很多
  不是总可以轻易跨平台
逻辑备份:
  mysqldump
  selcet * into outfile 'path/to/file' from tbname;

mysqldump

参数

-B:连接多个库
-A:备份所有库
-d:只备份表结构,没有行数据
-t:之备份行数据,没有表结构
-F:刷新binlog
-l:锁定所有表为只读

备份

mysqldump 库名 > /路径/文件
mysqldump -B 库名 库名2 库名3 > /xxx/xx.sql
mysqldump -B 库 | gzip> 文件  #gzip压缩
mysqldump 数据库名 表名1 表名2 … > 备份文件名 #备份表

恢复

mysql 库名< 文件#库名必须存在,且要与原来库名一致
source 文件 #必须处在那个数据库里

实例

[root@server1 ~]# mysqldump tb1 > tb1.sql
mysqldump: Got error: 1045: "Access denied for user 'root'@'localhost' (using password: NO)" when trying to connect
[root@server1 ~]# mysqldump tb1 -p123456 > tb1.sql
[root@server1 ~]# ll
总用量 12
-rw-------. 1 root root 1241 1月  12 10:11 anaconda-ks.cfg
-rw-r--r--. 1 root root 6335 3月  11 21:22 tb1.sql

MariaDB [(none)]> drop database tb1;
Query OK, 6 rows affected (0.00 sec)

MariaDB [(none)]> create database db1;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> use db1;
Database changed
MariaDB [db1]> source tb1.sql

MariaDB [db1]> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| employee      |
| t1            |
| t2            |
| t3            |
| t4            |
| t5            |
+---------------+
6 rows in set (0.00 sec)

配置文件

#[client] 客户端配置
#port  = 3306客户端默认连接端口

[mysqld]
datadir=/var/lib/mysql#数据库数据文件存放目录
socket=/var/lib/mysql/mysql.sock#为mysql客户端和服务器之间的本地通讯指定一个套接字文件
#user = mariadb mysql启动用户
#basedir= 安装目录
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd

[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid

#
# include all files from the config directory
#
!includedir /etc/my.cnf.d

~
~
~
~
"/etc/my.cnf" 19L, 570C 

子配置文件

[root@server1 ~]# ls /etc/my.cnf.d/
client.cnf  mysql-clients.cnf  server.cnf

架构

部署

安装mariadb

yum install mariadb-server.x86_64 -y

[root@server1 ~]# systemctl start mariadb.service
[root@server1 ~]# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n]
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n]
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n]
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n]
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n]
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

systemctl start mariadb.service

mysql -uroot -p密码

修改管理员密码

正常修改

[root@server1 ~]# mysqladmin -uroot -p password
Enter password:旧密码
New password:
Confirm new password:

忘记密码

[root@server1 ~]# systemctl stop mariadb.service
[root@server1 ~]# mysqld_safe --skip-grant-tables --skip-networking &
[1] 7435

[root@server1 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 1
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)]> use mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [mysql]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [mysql]> grant all on *.* to root@'localhost' identified by '123456';
Query OK, 0 rows affected (0.01 sec)
# 这一步也可以用于给其他ip账户远程登陆授权
MariaDB [mysql]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [mysql]> exit
Bye
[root@server1 ~]# pkill mysqld
[root@server1 ~]# systemctl restart mariadb
[1]+  完成                  mysqld_safe --skip-grant-tables --skip-networking
[root@server1 ~]# mysql -uroot -p123456

基础操作

库的增查改删

\G可以将结果以竖排的方式显示

# 查
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

# 增
MariaDB [(none)]> create database db1 charset utf8;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db1                |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.01 sec)
# 查看详细的建库指令
MariaDB [(none)]> show create database db1;
+----------+--------------------------------------------------------------+
| Database | Create Database                                              |
+----------+--------------------------------------------------------------+
| db1      | CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+--------------------------------------------------------------+
1 row in set (0.00 sec)


# 修改编码
MariaDB [(none)]> alter database db1 charset utf8;
Query OK, 1 row affected (0.00 sec)

# 使用这个数据库
use db1

# 删除数据库
drop database db1;

表的操作

切换表
use tablesname;
增:create table name(字段 类型,字段 类型);
查:show tables;
查看结构:describe/desc tablename;
查看创建时的配置:MariaDB [db1]> show create table tb1;

改:
增加字段:
alter table tablename modify 字段 类型;
改名
alter table tablename change 字段1 新字段1 旧/新类型 [完整性约束条件];
改表名
alter table tablename rename newtablename;
删除字段
alter table tablename drop 字段;
修改顺序
alter table tablename add 字段 类型 [完整性] first/(after 字段名)
alter table tablename change 字段 旧名 新名 新类型 [完整性] first/after


删:drop table tablename

指定引擎:create......ENGINE=xxx
alter tablename ai engine = xxx

表的约束规则

NOT NULL:非空

create table tb1 (id int not null);

default:设置默认值

create table tb1 (id int nut null default 111);

UNIQUE:唯一

create table tb1(id int unique);
create table t1(id int unique not null,ip int unique not null);
MariaDB [tb1]> desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   | PRI | NULL    |       |
| ip    | int(11) | NO   | UNI | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
#当一个值同时not null 和unique,先创建的那个会成为主键(innodb)

MariaDB [tb1]> create table t2(id int primary key auto_increment,ip int not null,host char(10) not null,unique(ip,host));#联合unique,host+ip组合不能相同
MariaDB [tb1]> desc  t2;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| ip    | int(11)  | NO   | MUL | NULL    |                |
| host  | char(10) | NO   |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+
3 rows in set (0.00 sec)


auto_increment

create table tb3(id int auto_increament primary key);自增且必须为主键

create table student( id int primary key auto_increment, name varchar(20), sex enum('male','female') default 'male' )auto_increment=3;设置步长

alter atble student auto_increment=3;
set session auth_increment_increment=2 #修改会话级别的步长

set session auto_increment_offset=5;设置自增的初始值,会话级,如果,offset比increment_increment的值大,offset会被忽略
什么时候会导致自增主键不连续:
1.插入值造成唯一键冲突(如插入自增id=10,但表里面已经有10了,插入失败,但是执行器会对自增键+1)
2.事务添加自增+1,之后回滚,数据被清除,自增没有
3.添加的数据,使用delete删除后,仍然按照删除前的位置增长,所以应该用truncate清空表
truncate tablename

primary key:主键,主键不可空不可重复,可以是单一字段,也可以是多字段组合

1. not null + unique 的第一个会被当成主键
create table department1( id int not null unique, #主键 name varchar(20) not null unique, comment varchar(100) );
2.primary key
create table department2( id int primary key, #主键 name varchar(20), comment varchar(100) );
3.单独指定
create table t4(id int, name varchar(20), comment varchar(100), primary key(id));
4.添加约束
alter table department4 modify id int primary key;
5.unique+not null联合主键
MariaDB [tb1]> create table t3(id int not null,ip int not null,phone int not null,unique(id,phone));
Query OK, 0 rows affected (0.01 sec)

MariaDB [tb1]> desc t3;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   | PRI | NULL    |       |
| ip    | int(11) | NO   |     | NULL    |       |
| phone | int(11) | NO   | PRI | NULL    |       |
+-------+---------+------+-----+---------+-------+

foreign key:外键,参照自另外一个表的唯一性索引。两个表必须都是innodb表,外键列必须建了索引,4.1.12版本后在建立外键时会自动创建索引;外键关系的两个列必须是数据类型相似,即可以互相转换类型的列

MariaDB [tb1]> desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   | PRI | NULL    |       |
| ip    | int(11) | NO   | UNI | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.01 sec)

MariaDB [tb1]> create table t5(name varchar(10),user_id int,foreign key(user_id) references t1(id));
Query OK, 0 rows affected (0.00 sec)

MariaDB [tb1]> desc t5;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name    | varchar(10) | YES  |     | NULL    |       |
| user_id | int(11)     | YES  | MUL | NULL    |       |
+---------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

create table employee( id int primary key, name varchar(20) not null, dpt_id int, foreign key(dpt_id) references department(id) on delete cascade # 级连删除 on update cascade # 级连更新 )engine=innodb;

值的操作

增:insert into tablename [(字段1,字段2...)]values(值1,值2),(),()...;#如果不写字段默认为全部
删:delete from tablename where 条件;
清空整张表:truncate tablename;
改:update tablename set 字段=值 where 条件;
查:select xx from tablename 条件

用户管理

用户格式:用户名@'白名单'

root@'192.168.226.148'
root@'192.168.226.%'
root@'localhost'
root@'server1'
root@'192.168.226.0/255.255.255.0'

添加、查看用户

mysql.user
MariaDB [db1]> create user [email protected] identified by '1';
Query OK, 0 rows affected (0.00 sec)

MariaDB [db1]> select user,host,password from mysql.user;
+-------+-----------------+-------------------------------------------+
| user  | host            | password                                  |
+-------+-----------------+-------------------------------------------+
| root  | localhost       | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| root  | 127.0.0.1       | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| root  | ::1             | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| test1 | 192.168.226.150 | *E6CC90B878B948C35E92B003C792C46C58C4AF40 |
+-------+-----------------+-------------------------------------------+
4 rows in set (0.00 sec)

修改用户密码

MariaDB [mysql]> update user set password=password('123') where user='test1' and host='192.168.226.150';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

删除用户

drop user 用户名@host;

权限管理

权限类型

ALL: SELECT,INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE 
ALL : 以上所有权限,一般是普通管理员拥有的 
with grant option:超级管理员才具备的,给别的用户授权的功能

权限管理

授权:grant 权的种类 on 库.表 to 用户 identified by '密码'
grant all on *.* to root@'192.168.226.%' identified by '123456';


查看授权:show grants for 用户
回收:revoke 权的种类 on 库.表  from 用户
刷新:flush privileges

内容管理

这里只列举部分,其他请看我前一篇博客

查询

语法

SELECT DISTINCT [group_concat,聚合,join,union]字段1,字段2... FROM 表名 
WHERE 条件[算数运算符,IN,NOT IN,NOT,any,exists,not exists,and,or] ,可以出现任何字段,但不能有聚合
GROUP BY field 
HAVING 筛选 ,因为在分组后,可以用聚合,只能用分组后的字段
ORDER BY field [asc,desc]
LIMIT 开始,单次最大输出数   #限制条数

优先级

from 
where 
group by 
select 
distinct 
having 
order by 
limit 
1.找到表:from 
2.拿着where指定的约束条件,去文件/表中取出一条条记录 
3.将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组 
4.执行select(去重) 
5.将分组的结果进行having过滤 
6.将结果按条件排序:order by 
7.限制结果的显示条数

查询关键字

between

SELECT emp_name,salary FROM employee WHERE post='teacher' AND salary>10000;

SELECT emp_name,salary FROM employee WHERE salary NOT BETWEEN 10000 AND 20000;

is null

SELECT emp_name,post_comment FROM employee WHERE post_comment IS NULL; 

SELECT emp_name,post_comment FROM employee WHERE post_comment IS NOT NULL;

in

SELECT emp_name,salary FROM employee WHERE salary IN (3000,3500,4000,9000) ;

LIKE模糊查询

通配符’%’ #配任意多个
SELECT * FROM employee 
WHERE emp_name LIKE 'eg%';

通配符’_’ #配一个
SELECT * FROM employee 
WHERE emp_name LIKE 'al__';

综合案例

create database db1 charset utf8;

use db1

create table department( id int primary key, name varchar(20) not null )engine=innodb character set utf8;

insert into department values (1,'教质部'), (2,'技术部'), (3,'人力资源部');

create table employee( id int primary key, name varchar(20) not null, dpt_id int, foreign key(dpt_id) references department(id)
    -> on delete cascade
    -> on update cascade
    -> )engine=innodb character set utf8;

insert into employee values (1,'yuan',1), (2,'nezha',2), (3,'egon',2), (4,'alex',2), (5,'wusir',3), (6,'李沁洋',3), (7,'皮卡丘',3), (8,'程咬金',3), (9,'程咬银',3) ;

级联删除

MariaDB [db1]> select * from employee;
+----+-----------+--------+
| id | name      | dpt_id |
+----+-----------+--------+
|  1 | yuan      |      1 |
|  2 | nezha     |      2 |
|  3 | egon      |      2 |
|  4 | alex      |      2 |
|  5 | wusir     |      3 |
|  6 | 李沁洋    |      3 |
|  7 | 皮卡丘    |      3 |
|  8 | 程咬金    |      3 |
|  9 | 程咬银    |      3 |
+----+-----------+--------+
9 rows in set (0.00 sec)

MariaDB [db1]> select * from department;
+----+-----------------+
| id | name            |
+----+-----------------+
|  1 | 教质部          |
|  2 | 技术部          |
|  3 | 人力资源部      |
+----+-----------------+
3 rows in set (0.00 sec)

MariaDB [db1]> delete from department where id=2;
Query OK, 1 row affected (0.00 sec)
MariaDB [db1]> select * from department;
+----+-----------------+
| id | name            |
+----+-----------------+
|  1 | 教质部          |
|  3 | 人力资源部      |
+----+-----------------+
2 rows in set (0.00 sec)

MariaDB [db1]> select * from employee;
+----+-----------+--------+
| id | name      | dpt_id |
+----+-----------+--------+
|  1 | yuan      |      1 |
|  5 | wusir     |      3 |
|  6 | 李沁洋    |      3 |
|  7 | 皮卡丘    |      3 |
|  8 | 程咬金    |      3 |
|  9 | 程咬银    |      3 |
+----+-----------+--------+
6 rows in set (0.00 sec)

级联修改

MariaDB [db1]> update department set id=2 where id=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MariaDB [db1]> select * from employee;
+----+-----------+--------+
| id | name      | dpt_id |
+----+-----------+--------+
|  1 | yuan      |      1 |
|  5 | wusir     |      2 |
|  6 | 李沁洋    |      2 |
|  7 | 皮卡丘    |      2 |
|  8 | 程咬金    |      2 |
|  9 | 程咬银    |      2 |
+----+-----------+--------+
6 rows in set (0.00 sec)

MariaDB [db1]> select * from department;
+----+-----------------+
| id | name            |
+----+-----------------+
|  1 | 教质部          |
|  2 | 人力资源部      |
+----+-----------------+
2 rows in set (0.00 sec)

数据备份

备份方式:
    热备:硬盘以内存中的一些数据进行备份
    冷备:数据库硬盘中的数据
    
按照备份后的文件内容:
    逻辑备份:一般是sql语句
    裸文件备份:拷贝数据库的文件,一般内容是二进制数据
按照每次备份的数据量
    完全备份:对数据库进行完整的备份
    增量备份:更新
    日志备份:二进制日志备份,当数据库宕机之后进行数据恢复的依据
冷备份的优点:
    备份简单,只需要拷贝相关文件即可
    易于跨平台
    恢复简单,只需要把文件恢复到相关位置即可
    恢复速度快,不需要执行任何sql语句,也不需要重新建立索引
冷备份的缺点
    冷备文件通常比逻辑文件大很多
    不能总可以轻易跨平台

逻辑备份

  1. select * into outfile 'path/to/file' from table_name
  2. mysqldump

原理:把数据从mysql数据库里以sql语句的形式直接输出

常用参数:

-B:同时备份多个库
-A:备份所有数据库
-d:只备份表结构,没有行数据
-t:只备份行数据,没有表结构
-F:刷新binlog
-l:锁定所有的表为只读


备份单个数据库
mysqldump -uroot -p* db1 > back_db1.sql;
备份多个
mysqldump -uroot -p* db1 db2 > back_db1.sql;
备份所有
mysqldump -uroot -p -A > all.sql
备份单个表
mysqldump -uroot -p* db1 stu_info > back_stu.sql

备份多个表
mysqldump -uroot -p* db1 stu_info table1 > back_stu.sql
使用gzip压缩备份数据库
mysqldump -uroot -p* db1 | gzip > back_db1.sql.gz
恢复
mysql < sql脚本文件
source /path/to/sql脚本文件

source ./back_db1.sql
需要先创建数据库再恢复!

MySQL

存储引擎
基础操作
其他操作
算数运算符
比较运算符
逻辑运算符
聚合函数
分组
视图
函数
谓词
集合运算
示例
数据类型

安装``yum install mariadb mariadb-server.x86_64 -y
``

启动systemctl start mariadb

查看3306端口是否启动ss -tanl | grep 3306

初始化mysql_secure_installation

mysql连接方式

TCP/IP:建立一个网络的连接请求,一般情况下客户端在一台服务器上,而实例在另外一台服务器上

命名管道:如果两个需要互相通信的进程在同一台服务器上,就可以使用命名管道,但是需要在配置文件中启用——enable-named-pipe选项

共享内存:通过在配置文件中添加——shared-memory实现,在实际连接的过程中需要添加——protocol=memory选项

unix套接字

vim /etc/my.cnf.d/clint.cnf
user=root
password=.....

可以免输入密码登录数据库

存储引擎

InnoDB\MyISAM\NDM\Memory\Archive\Federated\Maria

查询当前数据库支持的存储引擎show engines \G;

修改默认存储引擎配置文件

cat /etc/my.cnf
default-storage-engine=INNODB

建表时指定存储引擎
create table xx(xxxx) ENGINE=MyISAM

修改表的存储引擎alter table xx engine =xxxx;

InnoDB和MyISAM的区别

基础操作

mysql -u用户名 -p密码

use database_name选择数据库

create database database_name;创建数据库

show databases;查看所有数据库

select user();查询当前用户

set password = password('xxxxx');给当前数据库设置密码

增删改查

创建表

同一表中字段名不能相同,同一库中表名不能相同
创建表

create table table_name(
    字段名 类型 约束条件,
    字段名 类型 约束条件,
    ......
    字段名 类型 约束条件
);

create table table_name (xxxxx....,a1 int default 0);
使用default可以设置默认值

插入数据

insert into table_name (字段名,字段名...字段名) values (值,值....值);

当想插入默认值的时候,值处直接填入default就可以,或者直接略过,如果省略的字段没有默认值,那么值会变成null

insert into table_name (a1,a2,a3) select b1,b2,b3 from table_name;从别的表当中获取数字插入表中

insert into table_name(a1,a2,a3) selct b1,sum(b1),sum(b2) from table group by b1;

insert into table_name values (全部值);

update table_name SET 名=值......;

查看表结构、信息

select * form table_name;

show tables;

desc table_name;

show create table table_name;建表信息

select * from 库名.表名;

select distinct name from table;只返回不同的值,但是NULL也会被保留,distinct只能放在第一个列名之前

select name from table_name limit n;限制返回n行

select name from table_name limit n offset m;限制返回n行,从m行开始

排序检索

select name from table_name order by name1,name2...;取出一列或多列的名字,以此对输出进行排序,order by 语句只能出现在所有语句中的最后一条

select name from table_name order by n,m...;使用数字代表对应列的位置进行排列
select a1, a2, a3 from table_name order by 1;此处的order by1指以a1为基准进行排序

....order by name1 desc,name2;name1降序排序

排序当中,null的值会聚在一端,视具体数据库为准,且order by可以使用别名

修改

alter table 旧表名 rename 新表名;      /修改表名

alter table 表名 add 字段名[完整性约束条件] /增加字段;

alter table 表名 drop 字段名; /删除字段

alter table 表名 modify 字段名 类型 约束条件 change 旧字段名 新字段名 新数据类型 约束条件;  /修改字段

ALTER TABLE 表名
    ADD 字段名 数据类型 约束条件 FIRST;
    ADD 字段名 数据类型 约束条件 AFTER 字段名;
    CHANGE 旧字段名 新字段名 新数据类型 完整性约束条件 FIRST;
    MODIFY 字段名 数据类型 约束条件 AFTER 字段名;
//修改字段排列顺序,在新增字段时指定字段位置

alter table table_name modify 字段 类型 primary key auto_increment设置自增主键

updare table_name set field=value...  where....更新值

事务:
在同一个处理单元中执行一系列更新的集合

start transaction; --mysql
DML1;
DML2;
DML3;
...

commit/rollback;提交或回滚

删除

drop table table_name;删表

alter table table_name drop 字段;

delete from table_name where\orderby\limit;不使用where时删除全部行,但是保留表

where:where子句要紧跟在from子句之后,且不能和聚合函数一起使用

select .... from where name='xx';
where只能指定行的筛选条件

其他操作

注释

方式一
avatar

方式二
avatar

方式三
avatar

别名

select name as别名 from table_name;如果别名要使用中文,必须用双引号括起来而不是单引号

avatar

算数运算符

select price * 2 as 'doublue price' from table;从表中将价格这个字段乘以二的结果读出

四种运算符:+、-、*、/
当数字与NULL运算时,计算结果都是NULL,并且NULL的真值为不确定

比较运算符

=等于
<>不等于
>=大于等于
>大于
<=小于等于
<小于

select xxx from table where a_date < '2010-01-01';日期

select xxxx from table where price1 - price2 >= 1000;与算术运算符连用

当比较的是字符串类型的大小时,是按照字典的顺序来排,如'195'比'2'要小,因为1排在2之前

比较运算符不能用在NULL值上,如果想要判断值是否为NULL,可以使用 'is null'字段来判断,相反,需要使用'is not null'

逻辑运算符

  1. NOT:表示否定
    select xx from xxx where NOT price > 1000;
  2. AND\OR:并且\或,注意and的优先级要比or高!

select xx from xxx where a>10 and b < 50;

  1. 使用()来提升关系

聚合函数

COUNT:计算表中的行数

SUM:数据的合计

AVG:平均

MAX:最大

MIN:最小

select count(*) from table_name;
使用count(*)时,会包含null的行,如果使用count(列名),则不会计算null行

select sum(price) from table;

select distinct count(xx) from table;统计时去除重复

select sum(distinct price) from table;计算时去除重复

聚合函数不能和where一起使用!只有having子句、order by可以

分组

select xxx from table_name group by x1;
以x1为分组

group by 需要写在from\where语句之后
null也会被当做一组特定的数据处理.

select 列 from table_name where xxxxxx group by x1;先进行过滤在进行汇总

使用group by时,select 子句中不好出现聚合键以外的列名

group by的排序是随机的,且不能够使用别名

select a1,sum(b1) as sum_b1 from table group by a1 with rollup;此处在计算各组之和之后还会显示一行总和

指令的执行顺序:FROM--WHERE--GROUP BY--HAVING--SELECT--ORDER BY

avatar

having
having和where一样都是可以用来指定条件的语句,但是where只能指定记录行的条件,不能用来指定组的条件

having必须放在group by 后面

select xxx from table group by a1 having count(*)>2;此处的count为分组后各组各自统计的数

having子句中出现的列必须出现在groupby子句中,或者在聚合函数中使用

视图

视图不会保存数据,他保存的是从表中取数据用的select语句
create view 视图名字[(列名1,列名2...)] as select....

可以使用视图来创建视图,但是不推荐,同时,定义视图的时候不能使用order by语句,因为视图的数据行是没有顺序的

视图内的数据也可以进行和表一样的更新,但是要注意视图内数据和原表的关系,有些更新会导致错误

删除语句drop view name(列名...)

子查询

create view name xxx as select xxx from xxx group by;等同于
select xxx from (select xxx from xxx froup by xx)as name

标量子查询:返回一行一列的结果*


select a1,a2,a3,(select avg(price) from table) as avg_price from table;

select a1,avg(price) from table group by table having avg(price) > (select avg(price) from table);

关联子查询

SELECT product_type, product_name, sale_price
 FROM Product AS P1 
 WHERE sale_price > (SELECT AVG(sale_price)
 FROM Product AS P2 
 WHERE P1.product_type = P2.product_type
 GROUP BY product_type);

函数

  1. ABS()绝对值函数
  2. mod()求余
  3. round()四舍五入
  4. concat(a1,a2,a3)拼接字符串
  5. length()字符串重读
  6. lower()转为小写
  7. replace(对象,替换前,替换后)字符串替换
  8. subsrting(对象 from 起始位置 for 截取的字数)截取字符串
  9. current_date当前日期
  10. cast(转换前的值 as 想转换的类型)类型转换
  11. coalesce(数据,数据。。。)返回可变参数从左开始第一个不是null的值

谓词

LIKE:部分查询

SELECT *
 FROM SampleLike
 WHERE strcol LIKE 'ddd%';字符串开头一致

 SELECT *
 FROM SampleLike
 WHERE strcol LIKE '%ddd%';中间包含

 SELECT *
 FROM SampleLike
 WHERE strcol LIKE 'abc_ _';开头一致且后面跟两个字符

between

SELECT product_name, sale_price
 FROM Product
 WHERE sale_price BETWEEN 100 AND 1000;会包含临界值

in作为范围

SELECT product_name, purchase_price
 FROM Product
 WHERE purchase_price (not) IN (320, 500, 5000);

in作为子查询

SELECT product_name, sale_price
 FROM Product
 WHERE product_id (not) IN (SELECT product_id 
 FROM ShopProduct
 WHERE shop_id = '000C');从内层开始查

exist:判断是否存在满足某种条件的记录并返回真值

SELECT product_name, sale_price
 FROM Product AS P 
 WHERE EXISTS (SELECT *
 FROM ShopProduct AS SP 
 WHERE SP.shop_id = '000C'
 AND SP.product_id = P.product_id);exist只关心记录是否存在,与返回的列是那些并没有关系

CASE

CASE when <求值表达式> then <表达式>
     when <>           then <>
     ...
     else <表达式>
END

SELECT product_name,
 CASE WHEN product_type = '衣服'
 THEN 'A :' | | product_type
 WHEN product_type = '办公用品'
 THEN 'B :' | | product_type
 WHEN product_type = '厨房用具'
 THEN 'C :' | | product_type
 ELSE NULL
 END AS abc_product_type
 FROM Product;

 SELECT SUM(CASE WHEN product_type = '衣服' 
 THEN sale_price ELSE 0 END) AS sum_price_clothes,
 SUM(CASE WHEN product_type = '厨房用具' 
 THEN sale_price ELSE 0 END) AS sum_price_kitchen,
 SUM(CASE WHEN product_type = '办公用品' 
 THEN sale_price ELSE 0 END) AS sum_price_office
 FROM Product;

集合运算

union

取交集,运算对象的记录的列数必须相同,且运算对象的列的类型必须一致,orderby只能放在最后使用,union会进行去重,如果需要保留重复,则使用union all

select sname from stu_info union select name from cs;

自然连接

select * from stu_info natural join cs;
自然连接会自动处理,但是需要一样的字段名、属性,并且要设置主键

内联结

select a.p1,a.p2,b.t1 from att as a1 inner join byy as b on a.p1=b.t1;

on是用于写连接条件的,必须书写在from 和 where 之间

SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price, IP.inventory_quantity
 FROM ShopProduct AS SP INNER JOIN Product AS P 
 ON SP.product_id = P.product_id
 INNER JOIN InventoryProduct AS IP 
 ON SP.product_id = IP.product_id
 WHERE IP.inventory_id = 'P001';多表联结

外联结

SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price
FROM ShopProduct AS SP (RIGHT/LEFT) OUTER JOIN Product AS P 
ON SP.product_id = P.product_id;

与内联结相比,会包含原表中不存在的信息,使用left或right来确定谁是主表,最终的表中会包含主表中的所有信息

avatar

示例

create table stu_info(sno int primary key auto_increment, sname varchar(20), sclass varchar(20), ssex enum('男','女'));

alter table stu_info charset=utf8;

alter table stu_info modify ssex enum('男','女');
/////以上为错误演示

create table stu_info(sno int primary key auto_increment, sname varchar(20), sclass varchar(20), ssex enum('男','女')) charset=utf8;
////正确示例,这样在输入中文数据时不会变成问号

insert into stu_info (sname,sclass,ssex) values ('张三','信息安全1','男');

insert into stu_info (sno,sname,sclass,ssex) values ('100','李四','计算机2','女');

insert into stu_info (sname,sclass,ssex) values ('王五','软件3','男');


select * from stu_info;

avatar

alter table stu_info rename info_stu;修改表名

alter table stu_info add phoneno int(20);增加电话字段

alter table stu_info add birth date after ssex;
将新增加的生日字段加在性别后面

update stu_info set birth='2000-01-01' where sno='1';更新张三的生日

select sname from stu_info limit 2 offset 2;
从第二行限制返回两行

insert into stu_info values ('55','小明','通信2','女','2001-3-3','13485858588');


select * from stu_info where birth is not null;选出填写了生日的人

select count(*) from stu_info;查看表一共有几行

select max(sno) from stu_info;查看表中学号最大的

select ssex,count(*) from stu_info group by ssex;
计算男女人数

select ssex,count(*) from stu_info group by ssex having count(*) > 2;晒出人数多的性别

create table simp_stu (no int(11),name varchar(20)) charset=utf8;创建新表

insert into simp_stu select sno,sname from stu_info;从前表中获取数据插入其中

start transaction;
update stu_info set birth = '2000-10-10' where birth is null;
update stu_info set phoneno = '123456' where phoneno is null;
commit;使用事务进行批量更新

select substring(phoneno from 1 for 3) from stu_info;截取手机号的前三位

select * from stu_info where birth like '2001%';查询2001年生的

select sname, case when birth < '2001-1-1' then concat('A',birth)  else 'B' end as '时代' from stu_info;根据出生日期划分学生 


create table cs (name varchar(20),class varchar(20)) charset=utf8;创建课表
insert into cs values ('张三','信息论'),('张三','离散数学'),('王五','JAVA');
insert into cs values ('alias','C++');
select sname from stu_info union select name from cs;选取两张表学生的姓名

select a.sname,a.sclass,b.class from stu_info as a inner join cs as b on 
a.sname=b.name;选出既在学生表中,又在选课表中选了课的学生的信息

数据类型

数值型:int,unsigned int,decimal,float,double,real

字符型:

定长:char(),binary

变长:varchar(),varvinary

text,blob:保存较大文本使用,text只能保存字符数据,删除会导致留下“空洞”,可以使用OPTIMIZE TABLE 表名来进行优化

同时,可以使用索引来提高大短文本的精准查询的性能,例

create table t (in varchar(10),context blob,hash_value varchar(40));

insert into t values(1,repeat('xxx',2),md5(context));hash_value用于存储context的md5散列值

select * from t where hash_value=md5(repeat(xxx,2));

或者也可以使用前缀索引

desc select * from t where context like 'xxx%' \G;

时间日期型:
date,time,datetime,timestamp

date:年月日

datetime:年月日时分秒

time:时分秒

timestamp:需要经常插入或者更新当前日期为系统时间,格式YYYY-MM-DD HH:MM:SS

year:年

插入当前时间的函数:now()

枚举

ENUM:单选// 使用中文要记得指定charset=utf8

SET:多选

触发器

mysql> create table t_control(id int primary key);
Query OK, 0 rows affected (0.11 sec)

mysql> insert into t_control values (1);
Query OK, 1 row affected (0.05 sec)

mysql> create table t_bluerosehero(id int primary key,col int);
Query OK, 0 rows affected (0.11 sec)

mysql> delimiter //
mysql> create trigger tr_t_bluerosehero_bi before insert on t_bluerosehero
    -> for each row
    -> begin
    ->  if new.col>30 then
    ->          insert into t_control values (1);
    ->  end if;
    -> end;
    -> //
Query OK, 0 rows affected (0.08 sec)