Mysql进阶
- 一、事务
- ACID
- AUTOCOMMIT
- 二、并发一致性问题
- 1. 修改丢失
- 三、封锁
- 1. 封锁粒度
- 2. 封锁类型
- 读写锁
- 意向锁
- 3. 封锁协议
- 1. 一级封锁协议
- 2. 二级封锁协议
- 3. 三级封锁协议
- 4. 两段锁协议
- a. 概念
- b. 例子
- c. 两段锁是可串行化的充分条件
- d. 两段锁与死锁
- 四、MySQL系统变量
- 1. 查看系统变量
- 2. 设置系统变量
- a. 设置方式
- b. 设置全局变量
- c. 设置会话变量
- 五、MySQL体系结构
- 1. Client Connectors
- 2. Management Serveices & Utilities
- 3. Connection Pool
- 4. SQL Interface
- 5. Parser
- 6. Optimizer
- 7. Cache和Buffer(高速缓存区)
- 8. pluggable storage Engines
- 9. File System
- 六、MySQL存储引擎
- 1. 存储引擎介绍
- 2. 存储引擎特性
- 3. 有哪些存储引擎
- 4. 了解MySQL数据存储方式
- 七、MySQL存储引擎介绍
- 1. CSV存储引擎
- 2. Archive存储引擎
参考文章:学习Mysql这一篇就够了
参考文章1:MySQL面试题目
参考文章2:MySQL面试题目
参考文章:MySQL数据库学习宝典
参考文章:Mysql存储引擎
一、事务
ACID
1. 原子性(Atomicity)
事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。回滚可以用回滚日志(Undo Log)来实现,回滚日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。
2. 一致性(Consistency)
数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对同一个数据的读取结果都是相同的。
3. 隔离性(Isolation)
一个事务所做的修改在最终提交以前,对其它事务是不可见的。
4. 持久性(Durability)
一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。系统发生崩溃可以用重做日志(Redo Log)进行恢复,从而实现持久性。与回滚日志记录数据的逻辑修改不同,重做日志记录的是数据页的物理修改。
AUTOCOMMIT
MySQL 默认采用自动提交模式。也就是说,如果不显式使用START TRANSACTION语句来开始一个事务,那么每个查询操作都会被当做一个事务并自动提交。
二、并发一致性问题
1. 修改丢失
丢失修改指一个事务的更新操作被另外一个事务的更新操作替换。一般在现实生活中常会遇到,例如:T1 和 T2 两个事务都对一个数据进行修改,T1 先修改并提交生效,T2 随后修改,T2 的修改覆盖了 T1 的修改。
读脏数据
读脏数据指在不同的事务下,当前事务可以读到另外事务未提交的数据。例如:T1 修改一个数据但未提交,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。
不可重复读
不可重复读指在一个事务内多次读取同一数据集合。在这一事务还未结束前,另一事务也访问了该同一数据集合并做了修改,由于第二个事务的修改,第一次事务的两次读取的数据可能不一致。例如:T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
幻影读
幻读本质上也属于不可重复读的情况,T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
三、封锁
1. 封锁粒度
MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
应该尽量只锁定需要修改的那部分数据,而不是所有的资源。锁定的数据量越少,发生锁争用的可能就越小,系统的并发程度就越高。
但是加锁需要消耗资源,锁的各种操作(包括获取锁、释放锁、以及检查锁状态)都会增加系统开销。因此封锁粒度越小,系统开销就越大。
在选择封锁粒度时,需要在锁开销和并发程度之间做一个权衡。
2. 封锁类型
读写锁
- 互斥锁(Exclusive),简写为 X 锁,又称写锁。
- 共享锁(Shared),简写为 S 锁,又称读锁。
有以下两个规定
- 一个事务对数据对象 A 加了 X 锁,就可以对 A 进行读取和更新。加锁期间其它事务不能对 A 加任何锁。
- 一个事务对数据对象 A 加了 S 锁,可以对 A 进行读取操作,但是不能进行更新操作。加锁期间其它事务能对 A 加 S 锁,但是不能加 X 锁。
意向锁
使用意向锁(Intention Locks)可以更容易地支持多粒度封锁。
在存在行级锁和表级锁的情况下,事务 T 想要对表 A 加 X 锁,就需要先检测是否有其它事务对表 A 或者表 A 中的任意一行加了锁,那么就需要对表 A 的每一行都检测一次,这是非常耗时的。
意向锁在原来的 X/S 锁之上引入了 IX/IS,IX/IS 都是表锁,用来表示一个事务想要在表中的某个数据行上加 X 锁或 S 锁。有以下两个规定:
一个事务在获得某个数据行对象的 S 锁之前,必须先获得表的 IS 锁或者更强的锁;
一个事务在获得某个数据行对象的 X 锁之前,必须先获得表的 IX 锁。
通过引入意向锁,事务 T 想要对表 A 加 X 锁,只需要先检测是否有其它事务对表 A 加了 X/IX/S/IS 锁,如果加了
就表示有其它事务正在使用这个表或者表中某一行的锁,因此事务 T 加 X 锁失败。
3. 封锁协议
1. 一级封锁协议
事务 T 要修改数据 A 时必须加 X 锁,直到 T 结束才释放锁。
可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。
2. 二级封锁协议
在一级的基础上,要求读取数据 A 时必须加 S 锁,读取完马上释放 S 锁。
可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。
3. 三级封锁协议
在二级的基础上,要求读取数据 A 时必须加 S 锁,直到事务结束了i神才能释放 S 锁。
可以解决不可重复读的问题,因为读 A 时,其它事务不能对 A 加 X 锁,从而避免了在读的期间数据发生改变。
4. 两段锁协议
a. 概念
事务分为两个阶段:
第一阶段是获得封锁,也称为扩展阶段。
第二阶段是释放封锁,也称为收缩阶段。
b. 例子
T1:Slock A…Slock B…Xlock C…Unlock B…Unlock A…Unlock C
T2:Slock A…Unlock A…Slock B…Xlock C…Unlock C…Unlock B
T1符合两段锁协议,T2不符合。因为整个加锁阶段不能有解锁,解锁阶段不能有加锁。
c. 两段锁是可串行化的充分条件
- 多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行这些事务时结果相同时,这种调度策略是可串行化(Serializable)调度。
- 如果事务遵循两段锁协议,那么它们的并发调度是可串行化的。两段锁是可串行化的充分条件,但不是必要条件。
即:遵循两段锁协议,一定是可串行化的;不遵循两段锁协议,可能是可串行化的,也可能不是。
d. 两段锁与死锁
采用两段锁协议也有可能产生死锁,这是因为每个事务都不能及时解除被封锁的数据,可能会导致多个事务都要求对方已经封锁的数据而不能继续运行。
四、MySQL系统变量
在 MySQL 数据库,变量分为系统变量和用户自定义变量。系统变量以@@开头用户自定义变量以@开头
服务器维护着两种系统变量,即全局变量(GLOBAL VARIABLES)和会话变量(SESSION VARIABLES)。
全局变量影响 MySQL 服务的整体运行方式,会话变量影响具体客户端连接的操作。每一个客户端成功连接服务器后,都会产生与之对应的会话。会话期间,MySQL 服务实例会在服务器内存中生成与该会话对应的会话变量,这些会话变量的初始值是全局变量值的拷贝。
1. 查看系统变量
SESSION包含GLOBAL和SESSION
VARIABLES默认为SESSION VARIABLES
可以使用以下命令查看 MySQL 中所有的全局变量信息。
SHOW GLOBAL VARIABLES;
可以使用以下命令查看与当前会话相关的所有会话变量以及全局变量。
SHOW SESSION VARIABLES;
MySQL 中有一些系统变量仅仅是全局变量,例如 innodb_data_file_path,可以使用以下 3 种方法查看:
SHOW GLOBAL VARIABLES LIKE 'innodb_data_file_path';
SHOW SESSION VARIABLES LIKE 'innodb_data_file_path';
SHOW VARIABLES LIKE 'innodb_data_file_path';
MySQL 中有一些系统变量仅仅是会话变量,例如 MySQL 连接 ID 会话变量 pseudo_thread_id,可以使用以下 2 种方法查看。
SHOW SESSION VARIABLES LIKE 'pseudo_thread_id';
SHOW VARIABLES LIKE 'pseudo_thread_id';
MySQL 中有一些系统变量既是全局变量,又是会话变量,例如系统变量 character_set_client 既是全局变量,又是会话变量。
SHOW SESSION VARIABLES LIKE 'character_set_client';
SHOW VARIABLES LIKE 'character_set_client';
2. 设置系统变量
a. 设置方式
- 修改 MySQL 源代码,然后对 MySQL 源代码重新编译(该方法适用于 MySQL 高级用户,这里不做阐述)。
- 在 MySQL 配置文件(mysql.ini 或 mysql.cnf)中修改 MySQL 系统变量的值(需要重启 MySQL 服务才会生效)。
- 在 MySQL 服务运行期间,使用 SET 命令重新设置系统变量的值。
b. 设置全局变量
需要注意的是,更改全局变量只影响更改后连接客户端的相应会话变量,而不会影响目前已经连接的客户端的会话变量(即使客户端执行 SET GLOBAL 语句也不影响)。也就是说,对于修改全局变量之前连接的客户端只有在客户端重新连接后,才会影响到客户端。
- SET @@global.innodb_file_per_table=default;
- SET @@global.innodb_file_per_table=ON;
- SET global innodb_file_per_table=ON;
c. 设置会话变量
客户端连接时,当前全局变量的值会对客户端的会话变量进行相应初始化。设置会话变量不需要特殊权限,但客户端只能更改自己的会话变量,而不能更改其它客户端的会话变量。
- SET @@session.pseudo_thread_id=5;
- SET session pseudo_thread_id=5;
- SET @@pseudo_thread_id=5;
- SET pseudo_thread_id = 5;
五、MySQL体系结构
1. Client Connectors
接入方。支持很多协议(JDBC、ODBC、.NET、PHP、Python、PERL、C 等)
2. Management Serveices & Utilities
系统管理和控制工具,mysqldump、 mysql复制集群、分区管理等
3. Connection Pool
连接池:管理缓冲用户连接、用户名、密码、权限校验、线程处理等需要缓存的需求
4. SQL Interface
SQL接口:接受用户的SQL命令,并且返回用户需要查询的结果
5. Parser
解析器,SQL命令传递到解析器的时候会被解析器验证和解析。解析器是由Lex和YACC实现的
6. Optimizer
查询优化器,SQL语句在查询之前会使用查询优化器对查询进行优化
7. Cache和Buffer(高速缓存区)
查询缓存,如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据
8. pluggable storage Engines
插件式存储引擎。存储引擎是MySql中具体的与文件打交道的子系统
9. File System
文件系统,数据、日志(redo,undo)、索引、错误日志、查询记录、慢查询等
六、MySQL存储引擎
1. 存储引擎介绍
关系型数据库,就是用来存储各种数据信息的。根据不同业务场景,比如说:有的表简单,有的表复杂,有的表根本不用来存储任何长期的数据,有的表需要查询非常快。在我们实际的业务开发中,可能需要用到各种各样的表,不同的表也意味着存储不同类型的数据,数据的处理上也就会存在着差异。针对 MySQL 来说,它提供了很多类型的存储引擎来供我们选择,我们可以根据业务需求来选择不同的存储引擎,最大程度的发挥 MySQL 的强大之处。
2. 存储引擎特性
存储引擎是指定在表之上的,即一个库中的每一个表都可以指定选择存储引擎;
3. 有哪些存储引擎
我们可以使用命令:show engines;来查看 MySQL 支持哪些存储引擎,如下图所示。我们可以看到 MySQL 默认使用的存储引擎是 InnoDB(下图 MySQL 使用的版本为5.7.28)。
4. 了解MySQL数据存储方式
通过以下命令,查看具体存储为止
show variables like ‘datadir’
进入/usr/local/mysql/data 目录,再进入到 db_store 目录下,我们便能够很真实的看到数据库中的数据在硬盘中存储
七、MySQL存储引擎介绍
1. CSV存储引擎
a. 存储文件
- 数据是以CSV文件存储。
b. 存储引擎特点
- 不能定义索引,列定义必须为NOT
NULL,不能设置自增列;(缺点:不适用于大表或者数据查询、排序等处理操作)- CSV数据的存储需要用,逗号隔开,可直接编辑 CSV文件进行数据的编排(缺点:数据安全性低)
- 可以对硬盘中保存的表文件数据进行直接编辑xxx.CSV文件,但是不能将该文件删除然后上传自己的同名.CSV文件(该文件中可能还有额外一些和表相关的数据),我们只能对其中数据进行编辑操作。编辑之后,通过命令:flush table XXX表名的方式使其生效
c. 使用CSV存储引擎建表语句
CREATE TABLE `users_csv` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`age` int(11) NOT NULL,
`address` varchar(255) NOT NULL
) ENGINE=csv
d. 查看数据所在硬盘位置
.frm 为表结构文件;.CSV为数据文件,.CSM不了解是干嘛的
2. Archive存储引擎
a. 存储文件
- 数据是以ARZ文件存储。
b. 存储引擎
- 只支持 insert 和 select 两种操作;(缺点:不适用于对数据的处理操作)
- 只允许自增ID列建立索引(缺点:还是不方便数据的处理)
- 支持行级锁
- 不支持事务
- 优点:数据占用磁盘少
c. 使用Archive存储引擎建表语句
CREATE TABLE `users_archive` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=Archive
d. 查看数据所在硬盘位置
e. Archive对比InnoDB,使用函数批量存储1w条数据
//批量添加函数:
CREATE DEFINER=`root`@`%` PROCEDURE `users_archive_batchAdd`()
begin
declare i int;
set i=1;
while i<10000 do
INSERT INTO users_archive(id,name,age,address) VALUES(i,concat('James',i),i,concat('BeiJing',i));
set i=i+1;
end while;
end
命令:du -s -h *