表空间管理,事物,ACSR,隔离级别+锁+MVCC

1. 表空间管理

1.0 以下的配置,一般是在初始化之前就应该设置好的。

1.1 共享表空间

1.1.1 查询参数

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

1.1.2 设置共享表空间

方法一: 初始化时设置方法(建议)
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

1.2 临时表空间

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

例如某一事务的事务序号为T1,其对数据X进行修改,设X的原值是5,修改后的值为15,那么Undo日志为<T1, X, 5>,Redo日志为<T1, X, 15>。
也有把undo和redo结合起来的做法,叫做Undo/Redo日志,在这个例子中Undo/Redo日志为<T1, X, 5, 15>。
当用户生成一个数据库事务时,undo log buffer会记录被修改的数据的原始值,redo会记录被修改的数据的更新后的值。

1.3 undo表空间

Important
The number of undo tablespaces can only be configured when initializing a MySQL instance and is fixed for the life of the instance.

1.3.1 如何查看

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;   #触发自动回收的条件,单位是检测次数。

1.3.2 设置方法:

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 

1.4 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;

2 事务 Transaction

2.1 什么是事务?

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

2.2 什么是交易?

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

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

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

2.4事务生命周期

— 标准事务控制语句

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…
数据库停止。

3. 事务中的ACID如何保证?

3.1 关键名词

3.1.1 redo log

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

3.1.2 数据表空间

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

3.1.3 LSN 日志序列号

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

3.1.4 WAL : Write ahead log

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

3.1.5 脏页: Dirty pages

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

3.1.6 Checkpoint(CKPT)

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

3.1.7 DB_TRX_ID:

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

3.2 redo log 功能详解

3.2.1 redo 介绍

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

3.2.2 redo 工作原理图

略。

3.2.3 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日志的原理图
略。

4. 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空间

5. 隔离级别+锁+MVCC

以上三项特性,主要保证ACID中的“I”隔离性。

5.1 隔离级别(transaction_isolation)

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

5.2 脏读

事务工作期间,读到了 《未提交事务》 正在发生修改的脏页。

脏读模拟过程:
vim /etc/my.cnf
transaction_isolation=READ-UNCOMMITTED
mysql> select @@transaction_isolation;
±------------------------+
| @@transaction_isolation |
±------------------------+
| READ-UNCOMMITTED |
±------------------------+

5.3 不可重复读

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

5.4 幻读现象说明

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

6. 隔离级别 、锁 、MVCC

6.1 类型

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

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

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

6.3 MVCC是什么?

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

6.4 RR级别如何方式幻读现象

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

6.5 MySQL中的锁机制

6.5.1 作用

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

6.5.2 基于资源分类

#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执行计划时,会升级为表锁。

引擎层:针对索引进行加锁

record lock :记录锁 ----> 聚簇索引
GAP lock :间隙锁 ----> 辅助索引范围
Next lock :下一键锁 ----> record+GAP

1.5.3 锁的类型演示

准备测试表

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
1.5.4 加锁级别

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

  1. ACID - C(一致性保证) 特性保证

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

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

  1. InnoDB 核心特性总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值