主要内容:
PXC概述、部署PXC(自动故障恢复测试)、存储引擎、读锁/写锁、表锁/行锁、常用的存储引擎介绍
一、PXC概述
PXC(Percona XtraDB Cluster,简称PXC集群),是基于Galera的MySQL高可用集群解决方案,提供了多主复制、自动故障转移和数据一致性等特性。Galera Cluster是Codership公司开发的一套免费开源的高可用方案(MySQL发行版),PXC集群主要由两部分组成:Percona Server with XtraDB 和 Write Set Replication patches(使用了Galera library,一个通用的用于事务型应用的同步、多主复制插件);可以实现多个节点间的数据同步复制以及读写,并且可保障数据库的服务高可用及数据一致性;PXC与mariadb的集群maridb-cluster原理是一样的。
官网地址:Galera Cluster for MySQL | The world's most advanced open-source database cluster.
1、PXC主要特性
1)多主复制:
- PXC支持多主复制,这意味着每个节点都可以同时读写,没有单点故障。
- 所有节点都是对等的,任何节点都可以接受写操作。
2)数据一致性:
- PXC使用Galera Cluster的同步复制技术,确保所有节点上的数据一致性。
- 事务在所有节点上同时提交,避免了数据不一致的问题。
3)自动故障转移:
- 当某个节点发生故障时,其他节点会自动接管,确保服务的连续性。
- 无需手动干预,系统会自动检测并处理故障。
4)高可用性:
- PXC通过多节点部署和自动故障转移,提供了高可用性。
- 即使某个节点发生故障,集群仍然可以正常运行。
5)扩展性:
- PXC支持水平扩展,可以通过增加节点来提高集群的处理能力。
- 每个节点都可以处理读写请求,提高了系统的整体性能。
6)低延迟复制:
- PXC的复制是同步的,确保了低延迟的数据复制。
- 数据在所有节点上几乎同时更新,避免了数据延迟的问题。
2、PXC架构
基于Galera Cluster,主要由以下组件组成:
节点(Node):
每个节点都是一个独立的MySQL实例,运行在不同的服务器上。节点之间通过Galera复制协议进行通信,确保数据一致性。
Galera复制插件:
Galera复制插件是PXC的核心组件,负责管理节点之间的数据复制。它确保所有节点上的数据一致性,并处理故障转移和节点加入/退出等操作。
wsrep API:
wsrep API是Galera Cluster的接口,用于与MySQL集成。它提供了事务处理、数据复制和节点管理等功能。
3、端口介绍
① 3306:数据库对外服务的端口号
说明:这是MySQL的标准端口,用于客户端连接到数据库服务器。PXC节点通过这个端口提供数据库服务,客户端可以通过这个端口进行读写操作。
② 4444:SST端口(State Snapshot Transfer)
说明:SST用于全量同步,当一个新的节点加入集群时,它需要从现有节点获取完整的数据副本。PXC支持多种SST方法,如xtrabackup、rsync和mysqldump。4444端口用于请求和传输这些全量数据。
③ 4567:集群通信端口
说明:SST用于全量同步,当一个新的节点加入集群时,它需要从现有节点获取完整的数据副本。PXC支持多种SST方法,如xtrabackup、rsync和mysqldump。4444端口用于请求和传输这些全量数据。
④ 4568:IST端口(Incremental State Transfer)
说明:IST用于增量同步,相对于SST来说,IST只传输自上次同步以来的增量数据。当一个节点加入集群时,如果已经有部分数据,可以通过IST端口获取增量数据,而不是全量数据。
4、名词介绍
SST(State Snapshot Transfer):
- 全量同步:当一个新的节点加入集群时,它需要从现有节点获取完整的数据副本。SST通过4444端口进行全量数据的传输。
IST(Incremental State Transfer):
- 增量同步:相对于SST来说,IST只传输自上次同步以来的增量数据。当一个节点加入集群时,如果已经有部分数据,可以通过IST端口获取增量数据,而不是全量数据。
WS(write set):
- 写数据集:在PXC中,每个写操作(事务)都会生成一个写数据集(write set),这个写数据集包含了所有需要更新的数据和元数据。写数据集通过4567端口在节点之间进行复制,确保数据一致性。
部署PXC示例:
网络实验拓扑:
- 服务器角色:mysql1、mysql2、mysql3(三台相互独立的mysql服务器)
- Mysql1:IP为192.168.2.11、安装Percona-XtraDB-Cluster
- Mysql2:IP为192.168.2.12、安装Percona-XtraDB-Cluster
- Mysql3:IP为192.168.2.13、安装Percona-XtraDB-Cluster
提示:提前关闭防火墙和SELinux
步骤1:初始化环境准备(主机名解析、安装软件包)
① 配置服务器的名称解析
[root@mysql1 ~]# for i in {1..3}
> do
> echo -e "192.168.2.1$i\tmysql$i" >> /etc/hosts
> done
[root@mysql1 ~]# cat /etc/hosts
192.168.2.11 mysql1
192.168.2.12 mysql2
192.168.2.13 mysql3
[root@mysql2 ~]# for i in {1..3}
> do
> echo -e "192.168.2.1$i\tmysql$i" >> /etc/hosts
> done
[root@mysql1 ~]# cat /etc/hosts
192.168.2.11 mysql1
192.168.2.12 mysql2
192.168.2.13 mysql3
[root@mysql3 ~]# for i in {1..3}
> do
> echo -e "192.168.2.1$i\tmysql$i" >> /etc/hosts
> done
[root@mysql1 ~]# cat /etc/hosts
192.168.2.11 mysql1
192.168.2.12 mysql2
192.168.2.13 mysql3
② 准备yum源(参考:/linux-soft/4/pxc/Percona-XtraDB-Cluster-5.7.25-31.35-r463-el7-x86_64-bundle.tar)
[root@localhost ~]# cd pxc/
[root@ localhost pxc]# tar -xf Percona-XtraDB-Cluster-5.7.25-31.35-r463-el7-x86_64-bundle.tar
[root@ localhost pxc]# ls
[root@ localhost pxc]# cp *.rpm /var/www/html/mysql/ //复制解压的RPM包到/var/www/html/mysql/
[root@ localhost pxc]# cd /var/www/html/mysql/
[root@ localhost mysql]# createrepo -v .
[root@localhost ~]# scp /etc/yum.repos.d/mysql.repo root@192.168.2.11:/etc/yum.repos.d/
[root@localhost ~]# scp /etc/yum.repos.d/mysql.repo root@192.168.2.12:/etc/yum.repos.d/
[root@localhost ~]# scp /etc/yum.repos.d/mysql.repo root@192.168.2.13:/etc/yum.repos.d/
③ 安装软件包(qpress.x86_64、Percona-XtraDB-Cluster-*)
[root@mysql1 ~]# yum clean all
[root@mysql1 ~]# yum -y install qpress.x86_64 Percona-XtraDB-Cluster-*
[root@mysql1 ~]# id mysql
uid=997(mysql) gid=995(mysql) 组=995(mysql)
[root@mysql2 ~]# yum clean all
[root@mysql2 ~]# yum -y install qpress.x86_64 Percona-XtraDB-Cluster-*
[root@mysql3 ~]# yum clean all
[root@mysql3 ~]# yum -y install qpress.x86_64 Percona-XtraDB-Cluster-*
补充:如果有MySQL.,需要yum remove -y mysql-community-*卸载
步骤2:配置PXC服务(mysqld.cnf、mysqld_safe.cnf、wsrep.cnf)
[root@mysql1 ~]# ls /etc/percona-xtradb-cluster.conf.d/
mysqld.cnf mysqld_safe.cnf wsrep.cnf
① 分别修改3台服务器的mysqld.cnf配置文件
[root@mysql1 ~]# rm -rf /var/lib/mysql/* //建议清空原有MySQL数据目录
[root@mysql1 ~]# vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf
…
[mysqld]
server-id=11 //修改服务器标识(server-id=11)
datadir=/var/lib/mysql //工作目录
socket=/var/lib/mysql/mysql.sock //socket目录
log-error=/var/log/mysqld.log //日志目录
pid-file=/var/run/mysqld/mysqld.pid //进程目录
log-bin //开启binlog日志功能
log_slave_updates
expire_logs_days=7
…
[root@mysql2 ~]# rm -rf /var/lib/mysql/*
[root@mysql2 ~]# vim /etc/percona-xtradb-cluster.conf.d/mysqld.cnf
...
[mysqld]
server-id=12 //修改服务器标识(server-id=12)
datadir=/var/lib/mysql //工作目录
socket=/var/lib/mysql/mysql.sock //socket目录
log-error=/var/log/mysqld.log //日志目录
pid-file=/var/run/mysqld/mysqld.pid //进程目录
log-bin //开启binlog日志功能
log_slave_updates
expire_logs_days=7
...
[root@mysql3 ~]# rm -rf /var/lib/mysql/*
…
[mysqld]
server-id=13 //修改服务器标识(server-id=13)
datadir=/var/lib/mysql //工作目录
socket=/var/lib/mysql/mysql.sock //socket目录
log-error=/var/log/mysqld.log //日志目录
pid-file=/var/run/mysqld/mysqld.pid //进程目录
log-bin //开启binlog日志功能
log_slave_updates
expire_logs_days=7
…
② 分别修改3台服务器的mysqld_safe.cnf配置文件(使用默认配置即可)
[root@mysql1 ~]# vim /etc/percona-xtradb-cluster.conf.d/mysqld_safe.cnf
[mysqld_safe]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/lib/mysql/mysql.sock
nice = 0
[root@mysql2 ~]# vim /etc/percona-xtradb-cluster.conf.d/mysqld_safe.cnf
[mysqld_safe]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/lib/mysql/mysql.sock
nice = 0
[root@mysql3 ~]# vim /etc/percona-xtradb-cluster.conf.d/mysqld_safe.cnf
[mysqld_safe]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/lib/mysql/mysql.sock
nice = 0
③ 分别修改3台服务器的wsrep.cnf配置文件
[root@mysql1 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
…
wsrep_cluster_address=gcomm://192.168.2.11,192.168.2.12,192.168.2.13 //集群成员
wsrep_node_address=192.168.2.11 //本节点IP地址
wsrep_cluster_name=pxc-cluster //集群名
wsrep_node_name=mysql1 //本节点名
wsrep_sst_auth="sstuser:NSD2021@tedu.cn" //SST数据同步授权用户及密码
…
[root@mysql2 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
…
wsrep_cluster_address=gcomm://192.168.2.11,192.168.2.12,192.168.2.13 //集群成员
wsrep_node_address=192.168.2.12 //本节点IP地址
wsrep_cluster_name=pxc-cluster //集群名
wsrep_node_name=mysql2 //本节点名
wsrep_sst_auth="sstuser:NSD2021@tedu.cn" //SST数据同步授权用户及密码
…
[root@mysql3 ~]# vim /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
…
wsrep_cluster_address=gcomm://192.168.2.11,192.168.2.12,192.168.2.13 //集群成员
wsrep_node_address=192.168.2.13 //本节点IP地址
wsrep_cluster_name=pxc-cluster //集群名
wsrep_node_name=mysql3 //本节点名
wsrep_sst_auth="sstuser:NSD2021@tedu.cn" //SST数据同步授权用户及密码
…
步骤3:启动PXC服务
所有数据库服务器都在同一个集群里,基于主主结构,自动同步数据且强一致性;
① 启动集群服务(首次启动服务时间比较长)(mysql1操作)
[root@mysql1 ~]# systemctl start mysql@bootstrap.service //启动集群服务(集群环境初始化)
[root@mysql1 ~]# netstat -nlptu | grep :3306 //数据库服务端口
tcp6 0 0 :::3306 :::* LISTEN 2419/mysqld
[root@mysql1 ~]# netstat -nlptu | grep :4567 //集群通信端口
tcp 0 0 0.0.0.0:4567 0.0.0.0:* LISTEN 2419/mysqld
补充:mysql@bootstrap.service初始化集群服务,最先启动,且一般只需启动一次;
# 初始化数据库服务密码
[root@mysql1 ~]# grep password /var/log/mysqld.log //查找日志生成随机登录密码
2021-06-16T03:12:37.699513Z 1 [Note] A temporary password is generated for root@localhost: +KduIl_.)655
[root@mysql1 ~]# mysqladmin -uroot -p'+KduIl_.)655' password 'NSD2021@tedu.cn';
# 添加授权SST数据同步授权用户sstuser(授权:reload,lock tables,replication client,process)
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> grant reload,lock tables,replication client,process on *.* to sstuser@'localhost' identified by 'NSD2021@tedu.cn';
Query OK, 0 rows affected, 1 warning (0.00 sec)
② 启动mysql2、mysql3节点的mysql服务,其它节点将会自动同步mysql1服务器的数据、root初始密码、授权用户sstuser
[root@mysql2 ~]# systemctl start mysql //注意:启动的是mysql服务,不是mysqld
[root@mysql2 ~]# netstat -utnlp | grep :3306 //数据库服务端口
tcp6 0 0 :::3306 :::* LISTEN 2968/mysqld
[root@mysql2 ~]# netstat -utnlp | grep :4567 //集群通信端口
tcp 0 0 0.0.0.0:4567 0.0.0.0:* LISTEN 2968/mysqld
[root@mysql3 ~]# systemctl start mysql //注意:启动的是mysql服务,不是mysqld
[root@mysql3 ~]# netstat -utnlp | grep :3306 //数据库服务端口
tcp6 0 0 :::3306 :::* LISTEN 2968/mysqld
[root@mysql2 ~]# netstat -utnlp | grep :4567 //集群通信端口
tcp 0 0 0.0.0.0:4567 0.0.0.0:* LISTEN 2968/mysqld
步骤4:测试配置
① 在任意数据库服务器查看集群信息
mysql> show status like "%wsrep%"; //查找到以下信息
+----------------------------------+-------------------------------------------------------+
| Variable_name | Value |
+----------------------------------+-------------------------------------------------------+
| wsrep_incoming_addresses | 192.168.2.11:3306,192.168.2.12:3306,192.168.2.13:3306 |
| wsrep_cluster_weight | 3 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_ready | ON |
+----------------------------------+-------------------------------------------------------+
71 rows in set (0.01 sec)
解释说明:
- wsrep_incoming_addresses:加入Galera集群的节点地址
- wsrep_cluster_weight:Galera集群的权重
- wsrep_cluster_status:Galera集群的状态
(PRIMARY:节点处于集群PC中,尝试从集群中选取donor进行数据同步)
- wsrep_connected:Galera集群连接状态
- wsrep_ready:Galera集群准备状态
② 在任意数据库服务器访问集群,并授予测试用户(授予的用户,会同步到集群的其它成员)
mysql> grant all on db1.* to dbuser1@'%' identified by 'NSD2021@tedu.cn';
Query OK, 0 rows affected, 1 warning (0.48 sec)
mysql> show grants for dbuser1;
+--------------------------------------------------+
| Grants for dbuser1@% |
+--------------------------------------------------+
| GRANT USAGE ON *.* TO 'dbuser1'@'%' |
| GRANT ALL PRIVILEGES ON `db1`.* TO 'dbuser1'@'%' |
+--------------------------------------------------+
2 rows in set (0.00 sec)
③ 客户端192.168.2.5连接集群任意数据库服务器,创建库和表,并存取数据(mysql1)
[root@localhost ~]# mysql -udbuser1 -pNSD2021@tedu.cn -h192.168.2.11
mysql> create database db1 default charset utf8mb4;
Query OK, 1 row affected (0.01 sec)
mysql> create table db1.students(id int primary key auto_increment, name varchar(20));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into db1.students(name) values ('tom');
Query OK, 1 row affected (0.01 sec)
④ 客户端192.168.2.5连接集群任意数据库服务器查看数据(mysql2、mysql3)
[root@localhost ~]# mysql -udbuser1 -pNSD2021@tedu.cn -h192.168.2.12
mysql> select * from db1.students;
+----+------+
| id | name |
+----+------+
| 1 | tom |
+----+------+
1 row in set (0.00 sec)
[root@localhost ~]# mysql -udbuser1 -pNSD2021@tedu.cn -h192.168.2.13
mysql> select * from db1.students;
+----+------+
| id | name |
+----+------+
| 1 | tom |
+----+------+
1 row in set (0.00 sec)
步骤5:测试故障自动恢复
补充:停止3台服务器的任意一台主机的数据库服务,都不会影响集群其它数据库服务器的数据存取
① 情况1:停止mysql@bootstrap.service服务
[root@mysql1 ~]# systemctl stop mysql@bootstrap.service
# 在任意数据库服务器,存储数据并查看
[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> insert into db1.students(name) values('jerry');
Query OK, 1 row affected (0.01 sec)
mysql> select * from db1.students;
+----+-------+
| id | name |
+----+-------+
| 1 | tom |
| 5 | jerry |
+----+-------+
2 rows in set (0.00 sec)
补充:id字段设置了自动增长,所以在插入语句时,会按照自动增长的方式递增,但递增的顺序是根据集群拥有的服务器数量做参考,假设集群有2台服务器,则顺序可能为2、4、6...,有3台服务器,则顺序可能为3、6、9;原因为保证插入语句主键不会重复;(也可以指定字段插入,但不建议)
② 停止服务后,查看/var/lib/mysql/grastate.dat文件,与其它节点的seqno不一致
[root@mysql1 ~]# cat /var/lib/mysql/grastate.dat
# GALERA saved state
version: 2.1
uuid: e74df6e9-ceb6-11eb-904b-d65cf985a2a7
seqno: 6
safe_to_bootstrap: 0
[root@mysql2 ~]# cat /var/lib/mysql/grastate.dat
# GALERA saved state
version: 2.1
uuid: e74df6e9-ceb6-11eb-904b-d65cf985a2a7
seqno: -1
safe_to_bootstrap: 0
[root@mysql3 ~]# cat /var/lib/mysql/grastate.dat
# GALERA saved state
version: 2.1
uuid: e74df6e9-ceb6-11eb-904b-d65cf985a2a7
seqno: -1
safe_to_bootstrap: 0
常见报错:第一台数据库服务器暂停了初始化集群服务,虽不会影响集群其它数据库服务器的数据存取,但再次以该服务器重启初始化集群服务时,会提示报错
排错思路:查看/var/log/mysqld.log提示报错:It may not be safe to bootstrap the cluster from this node. It was not the last one to leave the cluster and may not contain all the updates. To force cluster bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .
原因分析:从此节点引导群集可能不安全。它不是最后一个离开集群的,并且可能不包含所有更新。要强制此节点进行群集引导,请手动编辑grastate.dat文件,并将safe_To_bootstrap设置为1。
解决办法:停止集群所有的数据库服务器,并在服务器上查看/var/lib/mysql/grastate.dat文件,找到具有最高seqno的节点(若有seqno相同,则选其一),并把safe_to_bootstrap的值改为1(默认情况下,最后离开集群的数据库服务器的seqno值可能最大)
③ 停止集群其它的mysql服务器
[root@mysql2 ~]# systemctl stop mysql
[root@mysql3 ~]# systemctl stop mysql //最后一个退出关闭服务
④ 查看所有mysql服务器,找到具有最高seqno的节点,并设置safe_to_boostrap的值改为1
[root@mysql3 ~]# vim /var/lib/mysql/grastate.dat
# GALERA saved state
version: 2.1
uuid: 50caf19c-ce5d-11eb-bb5b-5229ff45a12e
seqno: 10
safe_to_bootstrap: 1 //群集引导
[root@mysql3 ~]# systemctl start mysql@bootstrap.service
⑤ 再启动其它主机的mysql服务
[root@mysql1 ~]# systemctl start mysql
[root@mysql2 ~]# systemctl start mysql
⑥ 再次检查所有数据库服务器的/var/lib/mysql/grastate.dat文件,发现所有seqno值都同步了;
[root@mysql1 ~]# vim /var/lib/mysql/grastate.dat
# GALERA saved state
version: 2.1
uuid: 50caf19c-ce5d-11eb-bb5b-5229ff45a12e
seqno: -1
safe_to_bootstrap: 0
验证:查看故障恢复的数据库服务器数据,已自动恢复
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> insert into db1.students(name) values('jerry');
Query OK, 1 row affected (0.01 sec)
mysql> select * from db1.students;
+----+-------+
| id | name |
+----+-------+
| 1 | tom |
| 5 | jerry |
+----+-------+
2 rows in set (0.00 sec)
① 情况2:停止mysql服务
[root@mysql2 ~]# systemctl stop mysql
② 停止服务后,查看/var/lib/mysql/grastate.dat文件,与其它节点的seqno不一致
[root@mysql2 ~]# cat /var/lib/mysql/grastate.dat
# GALERA saved state
version: 2.1
uuid: e74df6e9-ceb6-11eb-904b-d65cf985a2a7
seqno: 9
safe_to_bootstrap: 0
[root@mysql1 ~]# cat /var/lib/mysql/grastate.dat
# GALERA saved state
version: 2.1
uuid: e74df6e9-ceb6-11eb-904b-d65cf985a2a7
seqno: -1
safe_to_bootstrap: 0
③ 在任意数据库服务器,存储数据并查看
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> insert into db1.students(name) values('ben');
Query OK, 1 row affected (0.01 sec)
mysql> select * from db1.students;
+----+-------+
| id | name |
+----+-------+
| 1 | tom |
| 5 | jerry |
| 7 | ben |
+----+-------+
2 rows in set (0.00 sec)
④ 再次启动mysql服务
[root@mysql2 ~]# systemctl start mysql
⑤ 再次检查数据库服务器的/var/lib/mysql/grastate.dat文件,发现所有seqno值都同步了;
[root@mysql2 ~]# cat /var/lib/mysql/grastate.dat
# GALERA saved state
version: 2.1
uuid: e74df6e9-ceb6-11eb-904b-d65cf985a2a7
seqno: -1
safe_to_bootstrap: 0
验证:查看故障恢复的数据库服务器数据,已自动恢复
[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn
mysql> insert into db1.students(name) values('ben');
Query OK, 1 row affected (0.01 sec)
mysql> select * from db1.students;
+----+-------+
| id | name |
+----+-------+
| 1 | tom |
| 5 | jerry |
| 7 | ben |
+----+-------+
2 rows in set (0.00 sec)
二、存储引擎
数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以获得特定的功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。MySQL支持很多存储引擎,包括MyISAM、InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDB Cluster、ARCHIVE等,其中InnoDB和BDB支持事务安全。
例如:查看数据库默认使用并支持的引擎
mysql> show engines; //DEFAULT表示默认使用的引擎
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
| CSV | YES | CSV storage engine | NO | NO | NO |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| InnoDB | DEFAULT | Percona-XtraDB, Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)
例如:查看当前表使用的存储引擎
mysql> show create table db1.students\G
*************************** 1. row ***************************
Table: students
Create Table: CREATE TABLE `students` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
例如:创建表时指定使用的存储引擎
mysql> create table db1.students2(id int primary key auto_increment, name varchar(20)) engine=myisam;
Query OK, 0 rows affected (0.00 sec)
mysql> show create table db1.students2;
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| students2 | CREATE TABLE `students2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 |
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
三、读锁与写锁,行锁与表锁
1、读锁和写锁
无论何时,只要有多个SQL需要同一时刻修改数据,都会产生并发控制的问题。解决这类经典问题的方法就是并发控制,即在处理并发读或者写时,可以通过实现一个由两种类型的锁组成的锁系统来解决问题。这两种锁就是共享锁和排他锁,也叫读锁和写锁。
读锁(共享锁):
- 特性:读锁是共享的,多个用户可以在同一时刻读取同一资源,互不干扰。
- 作用:确保在读取数据时,数据不会被其他事务修改,从而保证数据的一致性。
写锁(排他锁):
- 特性:写锁是排他的,一个写锁会阻塞其他所有的写锁和读锁。
- 作用:确保在写入数据时,只有一个用户能够执行写操作,防止其他用户读取或修改正在写入的同一资源,从而保证数据的一致性和完整性。
锁的优先级:
- 写锁的优先级通常高于读锁,以确保写操作的及时性和数据的一致性。
2、行锁和表锁
实际数据库系统中每时每刻都在发生锁定,锁也是有粒度的,提高共享资源并发行的方式就是让锁更有选择性,尽量只锁定需要修改的部分数据,而不是所有的资源,因此要进行精确的锁定。由于加锁也需要消耗资源,包括获得锁、检查锁是否解除、释放锁等,都会增加系统的开销;所谓的锁策略就是要在锁的开销和数据的安全性之间寻求平衡,这种平衡也会影响性能。每种MySQL存储引擎都有自己的锁策略和锁粒度,最常用的两种重要的锁策略分别是表锁和行锁。
表锁:
- 特性:表锁是开销最小的锁策略,它会锁定整张表。
- 作用:当用户对表进行写操作时,需要先获得写锁,这会阻塞其他用户对该表的所有读写操作。只有在没有写锁的情况下,其他读取的用户才能获得读锁,读锁之间是不相互阻塞的。
- 优点:速度快,开销小。
- 缺点:冲突多,并发性较低。
行锁:
- 特性:行锁只对指定的记录加锁,其他进程仍然可以对同一表中的其他记录进行操作。
- 作用:行锁可以最大程度地支持并发处理,但也带来了最大的锁开销。
- 优点:冲突少,并发性高。
- 缺点:速度慢,开销大。
3、锁策略的平衡
锁策略的选择需要在锁的开销和数据的安全性之间寻求平衡。不同的MySQL存储引擎有不同的锁策略和锁粒度,常见的两种重要锁策略是表锁和行锁。
表锁:适用于读操作频繁、写操作较少的场景,因为表锁的开销小,速度快,但并发性较低。
行锁:适用于写操作频繁、需要高并发的场景,因为行锁的冲突少,并发性高,但开销大,速度慢
四、常见存储引擎
MySQL支持多种存储引擎,每种存储引擎都有其独特的特性和适用场景。以下是三种常见的存储引擎:MyISAM、InnoDB和MEMORY。
1. MyISAM
默认存储引擎:MySQL 5.5之前的默认存储引擎。
优势:访问速度快。
适用场景:对事务的完整性没有要求,或以select、insert为主的应用。在Web、数据仓库中应用广泛。
特点:
① 不支持事务、外键。
② 文件存储:每个MyISAM表在磁盘上存储为3个文件,文件名和表名相同,扩展名分别是:
- .frm:存储表定义(表结构)。
- .myd:MYData,存储数据。
- .myi:MYIndex,存储索引。
[root@mysql1 ~]# ls /var/lib/mysql/db1/
db.opt students2.frm students2.MYD students2.MYI
2.InnoDB
默认存储引擎:MySQL 5.5之后的默认存储引擎。
适用场景:对事务的完整性有较高要求,在并发条件下要求数据的一致性,数据操作中包含读、插入、删除、更新。在计费系统、财务系统等对数据的准确性要求较高的系统中被广泛应用。
优点:提供了具有提交(Commit)、回滚(Rollback)、崩溃恢复能力的事务安全,支持外键。
缺点:相比较于MyISAM,写的处理效率差一点,并且会占用更多的磁盘空间来存储数据和索引。
特点:
① 自动增长列:InnoDB表的自动增长列必须是索引,如果是组合索引,也必须是组合索引的第一列。MyISAM表的自动增长列可以是组合索引的其他列。
② 外键约束:MySQL的存储引擎中只有InnoDB支持外键约束。注意:当某个表被其它表创建了外键参照,那么该表对应的索引和主键禁止被删除。
3.MEMORY
存储方式:用保存在内存中的数据来创建表,每个MEMORY表对应一个磁盘文件,格式是.frm。
适用场景:内容变化不频繁的代码表,作为统计操作的中间结果表,便于利用它速率快的优势高效地对中间结果进行分析。
特点:
① 数据存储:数据存放在内存中,默认使用HASH索引,访问速度特别快。
② 缺点:数据库服务一旦关闭,数据就会丢失,另外对表的大小有限制。
扩展:MyISAM与InnoDB存储引擎的区别
事务支持:
- InnoDB:支持事务。
- MyISAM:不支持事务。
锁机制:
- InnoDB:支持行级锁。
- MyISAM:支持表级锁。
MVCC(多版本并发控制):
- InnoDB:支持MVCC。
- MyISAM:不支持MVCC。
外键支持:
- InnoDB:支持外键。
- MyISAM:不支持外键。
全文索引:
- InnoDB:不支持全文索引。
- MyISAM:支持全文索引。
MyISAM:适用于读操作频繁、对事务要求不高的场景,访问速度快,但不支持事务和外键。
InnoDB:适用于对事务完整性有较高要求、需要高并发和数据一致性的场景,支持事务、外键和行级锁,但占用更多磁盘空间。
MEMORY:适用于数据变化不频繁、需要快速访问的场景,数据存储在内存中,访问速度极快,但数据易丢失且表大小有限制。
思维导图:
小结:
本篇章节为【第四阶段】RDBMS2-DAY5 的学习笔记,这篇笔记可以初步了解到 PXC概述、部署PXC(自动故障恢复测试)、存储引擎、读锁/写锁、表锁/行锁、常用的存储引擎介绍,除此之外推荐参考相关学习网址:
- 带你玩转Mysql高可用方案--PXC_pxc架构图-CSDN博客
Tip:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解。