MySQL数据库-存储引擎核心特性

MySQL 存储引擎

存储引擎相当于Linux 文件系统。
插件的模式存在。作用在表的一种属性。

存储引擎类型

Oracle MySQL :

mysql> show engines;

MRG_MYISAM
CSV
MyISAM
BLACKHOLE
PERFORMANCE_SCHEMA
InnoDB
ARCHIVE
MEMORY
FEDERATED
MySQL 5.5 版本以后,默认的引擎是InnoDB。

InnoDB核心特性

聚簇索引
AHI 自适应hash索引
change buffer
事务
MVCC 多版本并发控制
行级锁
外键
复制特性
支持热备
自动故障恢复(ACSR)
双写机制

存储引擎基础管理

1 使用 SELECT 确认会话存储引擎

SELECT @@default_storage_engine;

2 存储引擎(不代表生产操作)

会话级别:
set default_storage_engine=myisam;
全局级别(仅影响新会话):
set global default_storage_engine=myisam;
重启之后,所有参数均失效.

如果要永久生效:
写入配置文件
vim /etc/my.cnf
[mysqld]
default_storage_engine=InnoDB

存储引擎是表级别的,每个表创建时可以指定不同的存储引擎,但是我们建议统一为innodb.

3 SHOW 确认每个表的存储引擎

SHOW CREATE TABLE City\G;
SHOW TABLE STATUS LIKE 'CountryLanguage'\G

4 INFORMATION_SCHEMA 确认每个表的存储引擎

select table_schema,table_name ,engine from information_schema.tables where table_schema not in ('sys','mysql','information_schema','performance_schema');
Master [world]>show table status;
Master [world]>show create table city;

5 修改一个表的存储引擎

alter table t1 engine innodb;
批量替换: 
SELECT CONCAT("ALTER TABLE ",table_schema,".",table_name," ENGINE=INNODB;")
FROM information_schema.tables 
WHERE table_schema NOT IN ('sys','information_schema','performance_schema','mysql')
AND ENGINE!='INNODB' INTO OUTFILE '/tmp/alter.sql';

注意:此命令我们经常使用他,进行innodb表的碎片整理

6 如何批量修改

将zabbix库中的所有表,innodb替换为tokudb
select concat("alter table zabbix.",table_name," engine tokudb;") from
information_schema.tables where table_schema='zabbix' into outfile '/tmp/tokudb.sql';

InnoDB 体系结构

1 物理存储结构

宏观

city.frm       : 数据字典信息(列定义)
city.ibd       : 表空间数据文件,存储数据行和索引
ibdata1        : 共享(系统)表空间文件
ib_logfileN    : redo log文件,重做日志。
ibtmp1         : 临时表空间
ib_buffer_pool : 内存预热文件

微观

(1)ibd : 表空间数据文件,段---》区 ----》页
(2)ibdata1:https://dev.mysql.com/doc/refman/8.0/en/innodb-architecture.html
	#5.5 版本 :
	Data Dictionary,Double write,change buffer ,Undo,临时表,用户数据
	#5.6 版本 :
	Data Dictionary,Double write,change buffer ,Undo,临时表
	#5.7 版本 : 
	Data Dictionary,Double write,change buffer ,Undo
	#8.0 版本
	change buffer	
Data Dictionary :数据库当中所有表的结构、属性、状态、参数....
Double write    :自动故障恢复应用到的数据。
change buffer   :辅助索引需要更新数据。	
Undo            : 存储事务的回滚信息日志。
(3) ib_logfileN : 存储事务的前滚日志。内存数据页的变化。
(4) ibtmp1      :存储SQL处理过程中的中间数据(group by , having , join, union)。	

表空间存储管理方式

# 介绍 
在数据库引擎层,加入的逻辑的存储结构。来实现灵活的存储空间扩容。
MySQL  5.5 版本引入了表空间存储管理模式。
# 表空间类型 
-- 共享表空间 :ibdata1~ibdataN
5.5 版本的默认模式。用来存储所有的系统数据+用户数据(数据行+索引)。
ibdata文件默认是一个,不够用了可以进行扩容。

-- 独立表空间 :
5.6 版本+: 
默认采用独立表空间模式。每张表都是独立的表空间(t1.ibd)。
共享表空间保留下来,只保存系统相关的数据。

5.7 和 8.0 版本中,将ibdata1进一步的瘦身。

# 操作 
--- 查看和配置表空间模式
mysql> select @@innodb_file_per_table;
mysql> set global innodb_file_per_table=0;
mysql> set global innodb_file_per_table=1;

2 内存结构

innodb_buffer_pool 
介绍: 
	InnoDB最大的内存区域,官方建议最多可设置大小物理内存的80%。生产建议70%以下。
作用: 
	缓冲数据页、索引页、数据字典、AHI、change buffer 、DW
	数据页修改完成之后,会写入到磁盘表空间中。ibd frm  ibdata1文件。
参数: 
	mysql> select @@innodb_buffer_pool_size;

innodb_log_buffer
介绍: 
	用来存储内存数据页的变化。数据修改完成之后,会将日志写入到磁盘日志文件中(ib_logfileN)。

参数: 
	mysql> select @@innodb_log_buffer_size;

表空间管理

一般是在初始化之前就应该设置好的。

共享表空间

查询参数

mysql> select @@innodb_data_file_path;
mysql> select @@innodb_autoextend_increment;

设置共享表空间

方法一: 初始化时设置方法(建议)
# step1 :
vim /etc/my.cnf 
innodb_data_file_path=ibdata1:1024M;ibdata2:1024M;ibdata3:1024M:autoextend
# step2: 
mysqld --initialize-insecure ....

方法二: 后设置
#step1 : 
vim /etc/my.cnf 
innodb_data_file_path=ibdata1:(当前文件)M;ibdata2:1024M;ibdata3:1024M:autoextend

# step2 :
重启数据库: 
/etc/init.d/mysqld restart

例子: 
-- 修改配置文件
vim /etc/my.cnf 
错误的: 
innodb_data_file_path=ibdata1:128M;ibdata2:128M:autoextend

重启数据库,错误日志: 
vim /data/3306/data/db01.err
2020-03-25T02:24:27.942930Z 0 [ERROR] InnoDB: The innodb_system data file './ibdata1' is of a different size 4864 pages (rounded down to MB) than the 8192 pages specified in the .cnf file!

[root@db01 data]# du -sh ibdata1 
76M	ibdata1

正确的: 
innodb_data_file_path=ibdata1:76M;ibdata2:128M:autoextend

临时表空间

innodb_temp_data_file_path=ibtmp1:12M;ibtmp2:128M:autoextend:max:500M

undo表空间

如何查看
SELECT @@innodb_undo_tablespaces;  ---->3-5个    #打开独立undo模式,并设置undo的个数。
SELECT @@innodb_max_undo_log_size;               #undo日志的大小,默认1G。
SELECT @@innodb_undo_log_truncate;               #开启undo自动回收的机制。
SELECT @@innodb_purge_rseg_truncate_frequency;   #触发自动回收的条件,单位是检测次数。

设置方法
innodb_undo_tablespaces=3           
innodb_max_undo_log_size=128M
innodb_undo_log_truncate=ON
innodb_purge_rseg_truncate_frequency=32


[root@db01 data]# cat /etc/my.cnf
[mysqld]
user=mysql
basedir=/data/app/mysql 
datadir=/data/3306/data
server_id=6
socket=/tmp/mysql.sock 
#log_bin=1
#gtid_mode=ON
#enforce_gtid_consistency=ON
secure-file-priv=/tmp
innodb_data_file_path=ibdata1:128M;ibdata2:128M:autoextend
innodb_temp_data_file_path=ibtmp1:128M;ibtmp2:128M:autoextend:max:500M
innodb_undo_tablespaces=3           
innodb_max_undo_log_size=128M
innodb_undo_log_truncate=ON
innodb_purge_rseg_truncate_frequency=32
[client]
socket=/tmp/mysql.sock
[root@db01 data]# 


重新初始化MySQL 
mysqld --initialize-insecure --user=mysql --basedir=/data/app/mysql --datadir=/data/3306/data 

General Tablespace

参考: 
https://dev.mysql.com/doc/refman/5.7/en/general-tablespaces.html

CREATE TABLESPACE `ts1` ADD DATAFILE '/my/tablespace/directory/ts1.ibd' Engine=InnoDB;
CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;
ALTER TABLE t2 TABLESPACE ts1;
 

事务 Transaction

什么是事务

伴随着“交易”类的业务需求,支持的一种工作模式。

什么是交易

以物换物
货币换物
虚拟货币换物
现实生活中,必须要保证交易的平衡和等价。
互联网的盛行,将交易搬到了线上进行。在线上(计算机)发生的交易行为,也要保证他的等价和平衡。
所以,事务,就是在计算机交易类程序中保证交易等价、平衡的工作模式。

事务的ACID(atomicity, consistency, isolation, durability.)四项特性

A : 原子性
事务中的所有操作,都是一个完整的整体。要么全成功,要么全失败。不能出现中间状态。
C :一致性
事务发生 前 中 后,数据应当保证一致状态。数据不会受到任何的破坏。数据最终一致是事务的最终目的。
I :隔离性
多事务工作期间是互相不影响的。
D :持久性
事务工作完成(commit),数据保证永久不丢失。数据落盘。

事务生命周期

— 标准事务控制语句
begin;/start transaction; — 开启事务。
commit; — 提交事务。
rollback; — 回滚事务。

— 标准的事务语句
单条或多条 DML语句: update,delete ,insert, select

— 事务操作演示
mysql> begin;
mysql> delete from city where id=1;
mysql> delete from city where id=2;
mysql> delete from city where id=200;
mysql> commit;

mysql> begin;
mysql> delete from city where id=1000;
mysql> delete from city where id=2000;
mysql> rollback;

— 自动提交机制
— 介绍
select @@autocommit;
作用:在没有使用begin 显式触发开的DML操作,MySQL会在此条命令执行完成后自动提交事务。
关闭自动提交之后,所有事务必须显式commit,才能提交成功。
begin; — 隐式触发。
delete 。。。。。
commit — 隐式提交。

— 配置
临时生效:
mysql> set global autocommit=0;
重新登录会话生效。

永久配置:
vim /etc/my.cnf
autocommit=0
重启生效。

— 触发隐式提交的特殊情况
begin
a
b

事务期间发生了一下操作,会触发隐式提交
begin
SET AUTOCOMMIT = 1
DDL语句: (ALTER、CREATE 和 DROP)
DCL语句: (GRANT、REVOKE 和 SET PASSWORD)
锁定语句:(LOCK TABLES 和 UNLOCK TABLES)
TRUNCATE TABLE
LOAD DATA INFILE
SELECT FOR UPDATE

---- 触发隐式回滚的特殊情况
中间命令执行失败
会话结束: 窗口关闭,kill…
数据库停止。

事务中的ACID如何保证?

redo log

重做日志。
磁盘文件: ib_logfile0~1 ,48M , 轮询使用
内存缓冲: redo log buffer,redo内存区域

数据表空间

磁盘区域
ibd :存储 数据行和索引
buffer pool:缓冲区池,数据和索引的缓冲

LSN 日志序列号

磁盘数据页
buffer pool
redo文件
redo buffer
MySQL 每次数据库启动,都会比较磁盘数据页和redolog的LSN,必须要求两者LSN一致数据库才能正常启动

WAL : Write ahead log

日志优先写的方式实现持久化

脏页: Dirty pages

内存脏页,内存中发生了修改,没写入到磁盘之前,我们把内存页称之为脏页.

Checkpoint(CKPT)

MySQL维护着检查点队列(checkpoint list),就是将脏页刷写到磁盘的动作

DB_TRX_ID:

事务号,InnoDB会为每一个事务生成一个事务号,伴随着整个事务生命周期.

D----redo log 功能详解

redo 介绍

重做日志。
内容记录:内存数据页的变化日志。
主要保证:ACID中的“D”的特性,对于AC也有相关辅助作用。

redo 工作原理图

在这里插入图片描述

A----Undo日志的功能详解

undo 介绍

回滚日志。
内容: 记录的是事务操作的逆向操作。
主要保证: ACID中的“A”的特性,实现rollbackup回滚的功能。也是MVCC特性的主要保障。所以对于C和I也有保证。
undo最多128个segments。96个在undo tablespace中,32个在temp tablespace。
每个段默认1024槽位。

Internally, InnoDB adds three fields to each row stored in the database. A 6-byte DB_TRX_ID field indicates the transaction identifier for the last transaction that inserted or updated the row. Also, a deletion is treated internally as an update where a special bit in the row is set to mark it as deleted. Each row also contains a 7-byte DB_ROLL_PTR field called the roll pointer. The roll pointer points to an undo log record written to the rollback segment. If the row was updated, the undo log record contains the information necessary to rebuild the content of the row before it was updated. A 6-byte DB_ROW_ID field contains a row ID that increases monotonically as new rows are inserted. If InnoDB generates a clustered index automatically, the index contains row ID values. Otherwise, the DB_ROW_ID column does not appear in any index.

undo日志的原理图

在这里插入图片描述

ACSR 自动故障恢复的实现逻辑

begin;
update set a=17 —> a=18 ;
未提交。

  1. 发起更新语句,从磁盘将t1.ibd,page_no=1001数据页+LSN=100, 加载到buffer pool中。
  2. 更新buffer pool中数据页之前,首先申请undo slot,将修改的“逆操作”日志写入到undo中。
  3. 生成当前事务 DB_TRX_ID(6字节)+ DB_ROLL_PTR(7字节)。
  4. 开始修改buffer_pool中数据页,更新LSN=101。
  5. 内存数据页,修改的过程日志+LSN=101 ,记录到redo buffer中。
  6. 假设此次事务的日志,随着其他事务的提交,事务日志顺便刷写到了redo日志文件中。

此时如果出现宕机(CRASH ),下次启动时的工作过程:

  1. 启动数据库引擎。
  2. InnoDB自动检查,磁盘数据页和redo log的LSN的大小。发现redo LSN> page LSN,立即出发CR过程。
  3. 前滚: 加载历史数据页+redo log到内存 。 通过redo log 重做事务,构造脏页。
  4. 检查到此次事务,并没有commit标记。除法回滚动作。
  5. 根据 DB_TRX_ID(6字节)+ DB_ROLL_PTR(7字节),从undo segment 的slot中此次事务的undo日志,进行回滚。
  6. 所有工作做完,数据库实例正常启动。
  7. 另外MySQL提供DoubleWrite机制,防止Page particularly fsync 。DWB默认在共享表空间中,默认2M空间

I----隔离级别+锁+MVCC

主要保证ACID中的“I”隔离性。

隔离级别(transaction_isolation)

作用: 主要提供了“读”的隔离性。
读是什么?
select ,update ,delete ,insert 都要牵扯到读数据页。
类型 :
RU : 读未提交。脏读、不可重复读、幻读
RC :读已提交。不可重复读、幻读
RR :可重复读。幻读
SR :可串行化。
控制参数:
mysql> select @@transaction_isolation;

脏读

事务工作期间,读到了 《未提交事务》 正在发生修改的脏页。
脏读模拟过程:
vim /etc/my.cnf
transaction_isolation=READ-UNCOMMITTED
mysql> select @@transaction_isolation;
±------------------------+
| @@transaction_isolation |
±------------------------+
| READ-UNCOMMITTED |
±------------------------+

不可重复读

在同一个事务窗口,做相同数据的读取,得到的是不同的值。

幻读现象说明

在事务更新过程中,出现了其他事务已经已提交数据幻行。

类型

transaction_isolation=xxxx,默认是RR。
RC :不可重复读、幻读。
RR :幻读
SR
RU

RR级别下如何防止不可重复读

RR级别下通过MVCC(多版本并发控制)技术,防止不可重复读现象。

MVCC是什么

每次开启一个全新的事务窗口(begin),都会生成当前最新的一致性快照(undo),直到事务commit或者rollback
此次事务,都会在此快照中进行操作。
我们也把这种技术,称之为一致性快照读取(一致性非锁定读)。
可以大大提高事务的并发能力。

RR级别如何方式幻读现象

RR级别下,提供了GAP(间隙锁),next-lock(下一键锁)锁定功能来预防幻读。

MySQL中的锁机制

作用
事务隔离性:主要提供写隔离
归根结底是用来保护“资源”不被争用。

基于资源分类

# 1. 内存资源 :
Latch(闩锁): mutex,rw-lock
作用: 控制内存中的线程使用资源的一种锁。防止数据页被意外置换出去。
线程对于数据页修改:需要申请mutex
线程对于数据页读取:需要申请rw-lock

# 2. 存储资源
server层:

— Matedata lock :元数据锁
触发条件:
DDL操作: alter
备份时会触发。FTWRL:Flush table with read lock

— table lock :表锁
在InnoDB中,虽然锁粒度是行锁,也有可能触发表锁。
lock tables t1 read;
从行锁升级至表锁。例如update 操作 where条件出现 ALL,Index执行计划时,会升级为表锁。

# 3引擎层:针对索引进行加锁
record lock :记录锁 ----> 聚簇索引
GAP lock :间隙锁 ----> 辅助索引范围
Next lock :下一键锁 ----> record+GAP

锁的类型演示
# 准备测试表      
create table test(
id int primary key not null auto_increment ,
num int not null ,
name varchar(20) not null
)charset utf8mb4;
insert into test values
(1,1,'a'),
(2,3,'b'),
(3,5,'c'),
(4,10,'d'),
(5,11,'aa'),
(6,13,'bb'),
(7,15,'cc'),
(8,30,'dd'),
(9,35,'aaa'),
(10,40,'baa'),
(11,50,'caa'),
(12,53,'daa'),
(13,55,'aas'),
(14,60,'bbs'),
(15,75,'ccs');
commit;
alter table test add index idx(num);

# matedata lock 
session A: 
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test;
mysql> update test set num=36 where id=10;

session B: 
drop table test;

session C: 
show processlist;

#table lock 


# record lock 
where id= 

# gap  --> RR
session A : 
mysql> begin;
mysql> update test set name='oldguo' where num<10;

session B: 
mysql> begin;
mysql> insert into test values(16,4,'oldboy');

session C: 
mysql> select * from innodb_lock_waits\G
加锁级别

IX 意向排他锁
X 写锁 排他锁
IS 意向共享锁
S 读锁 共享锁
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html

     X	     IX	         S	         IS

X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible

C----(一致性保证) 特性保证

数据页最终一致:
undo
redo
ACSR
DW
事务工作期间数据最终一致
transaction_isolation 读一致性
LOCK 写一致性
MVCC 一致性快照读,一致性非锁定读

以上所有技术体现,都是为了保证数据最终一致。

InnoDB 核心特性总结

事务(ACID)
MVCC
ACSR
Double Write
行级锁
change buffer
聚簇索引
AHI
热备
主从复制

InnoDB 重要参数

innodb_flush_log_at_trx_commit=0/1/2

作用:
控制redo log 刷新磁盘策略
参数值介绍:
1: 默认值。每次事务提交刷写redo buffer 到os cache,立即fsync()到磁盘。
能够真正保证ACID中的D的特性。双一标准之一。
2: 每次commit,刷写redo buffer到OS cache,每秒钟fsync()到磁盘。
如果是边缘业务或者离线业务可以使用。有一定风险,在服务器crash掉,有可能丢失1s事务。
0: 每秒刷新redo buffer 到OS cache,然后fsync()到磁盘。

innodb_flush_method 刷盘方式

作用: 控制 buffer pool 和redo buffer 数据和日志刷写磁盘的方式

fsync : 默认值。刷新数据页和redobuffer 到磁盘,都是先刷到os cache ,再fsync()到磁盘
O_DIRECT : 刷写数据页时,直接跨过OS Cache ,刷写到磁盘。redo buffer先刷到os cache ,再fsync()到磁盘
建议使用高IO能力的存储配合O_DIRECT.
fsync: InnoDB uses the fsync() system call to flush both the data and log files. fsync is the default setting.

O_DIRECT: InnoDB uses O_DIRECT (or directio() on Solaris) to open the data files, and uses fsync() to flush both the data and log files. This option is available on some GNU/Linux versions, FreeBSD, and Solaris.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值