- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
提供与MySQL服务器建立的支持。目前几乎支持所有主流的服务端编程技术,例如常见的 Java、C、Python、.NET等,它们通过各自API技术与MySQL建立连接
负责存储和管理客户端与数据库的连接,一个线程负责管理一个连接。
例如备份恢复、安全管理、集群管理等
用于接受客户端发送的各种SQL命令,并返回用户需要查询的结果。比如DML、DDL、存储过程、视图、触发器等。
负责将请求的SQL解析生成一个“解析树”。然后根据一些MySQL规则进一步检查解析树是否合法。
当“解析树”通过解析器语法检查后,将交由优化器将其转为执行计划,然后与存储引擎交互
缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,权限缓存,引擎缓存等。如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据
存储引擎负责MySQL中数据的存储和提取,与底层系统文件进行交互。MySQL存储引擎是插件式的,服务器中的查询执行引擎通过接口与存储引擎进行通信,接口屏蔽了不同存储引擎之间的差异。现在有很多存储引擎,各有各的特点,最常见的是MyISAM和InnoDB。
该层负责将数据库的数据和日志存储在文件系统之上,并完成与存储引擎的交互,是文件的物理存储层。主要包含日志文件、数据文件、配置文件、pid文件、socket文件等。
半双工:指的某一时刻,要么发送数据,要么接收数据,不能同时。例如早期对讲机
单工:只能发送数据或只能接收数据。例如单行道
等级变换策略
a < b and a = 5 改为 b>5 and a=5
基于联合索引,调整条件位置等
优化count、max、min等函数
innoDB引擎min函数只需要找索引最左边,max找索引最右边。
MyISAM引擎count(*)不需要计算,直接返回
提前终止查询,使用了limit查询,获取到所需的数据就返回
in的优化,MySQL对in的查询,会先进行排序,再采用二分法查找数据
存储引擎负责MySQL中的数据的存储和提取,是与文件打交道的子系统,它是根据MySQL提供的文件访问层抽象接口定制的一种文件访问机制,这种机制叫做存储引擎。
通过SHOW ENGINES命令,可以查看当前数据库支持的引擎信息。
在5.5版本之前默认采用MyISAM存储引擎,从5.5开始采用InnoDB存储引擎。
InnoDB和MyISAM对比
InnoDB支持事务和外键,具有安全性和完整性,适合大量insert或update操作
MyISAM不支持事务和外键,它提供高速存储和检索,适合大量的select查询操作
InnoDB支持行级锁,锁定指定记录。基于索引来加锁实现
MyISAM支持表级锁,锁定整张表
InnoDB主键使用了聚集索引,索引和记录在一起存储,既缓存索引,也缓存记录。
MyISAM使用非聚集索引,索引和记录分开,有单独的数据文件
MyISAM使用表锁,写操作并发低
InnoDB读写阻塞可以与隔离级别有关,可以采用MVCC(多版本并发控制)来支持高并发
InnoDB表对应两个文件,一个.frm表结构文件,一个.ibd数据文件。InnoDB最大支持64TB;
MyISAM表对应三个文件,一个.frm表结构文件,一个MYD表数据文件,一个.MYI索引文件。从MySQL5.0开始默认限制是256TB
InnoDB存储结构
下面是InnoDB引擎架构图,主要分为内存结构和磁盘结构两大部分。
内存结构主要包括Buffer Pool、Change Buffer、Adaptive Hash Index和Log Buffer四大组件。
free page :空闲page,未被使用
clean page:被使用page,数据没有被修改过
dirty page:脏页,被使用page,数据被修改过,页中数据和磁盘的数据产生了不一致
针对上述三种page类型,InnoDB通过三种链表结构来维护和管理
free list :表示空闲缓冲区,管理free page
flush list:表示需要刷新到磁盘的缓冲区,管理dirty page,内部page按修改时间排序。脏页既存在于flush链表,也在LRU链表中,但是两种互不影响,LRU链表负责管理page的可用性和释放,而flush链表负责管理脏页的刷盘操作。
lru list:表示正在使用的缓冲区,管理clean page和dirty page,缓冲区以midpoint为基点,前面链表称为new列表区,存放经常访问的数据,占63%;后面的链表称为old列表区,存放使用较少数据,占37%。
普通LRU:末尾淘汰法,新数据从链表头部加入,释放空间时从末尾淘汰
改性LRU:链表分为new和old两个部分,加入元素时并不是从表头插入,而是从中间midpoint位置插入,如果数据很快被访问,那么page就会向new列表头部移动,如果数据没有被访问,会逐步向old尾部移动,等待淘汰。每当有新的page数据读取到buffer pool时,InnoDb引擎会判断是否有空闲页,是否足够,如果有就将free page从free list列表删除,放入到LRU列表中。没有空闲页,就会根据LRU算法淘汰LRU链表默认的页,将内存空间释放分配给新的页。
show variables like '%innodb_page_size%'; //查看page页大小
show variables like '%innodb_old%'; //查看lru list中old列表参数
show variables like '%innodb_buffer%'; //查看buffer pool参数
建议:将innodb_buffer_pool_size设置为总内存大小的60%-80%,
innodb_buffer_pool_instances可以设置为多个,这样可以避免缓存争夺。
ChangeBuffer占用BufferPool空间,默认占25%,最大允许占50%,可以根据读写业务量来进行调整。参数innodb_change_buffer_max_size;
3. Adaptive Hash Index:自适应哈希索引,用于优化对BP数据的查询。InnoDB存储引擎会监控对表索引的查找,如果观察到建立哈希索引可以带来速度的提升,则建立哈希索引,所以称之为自适应。InnoDB存储引擎会自动根据访问的频率和模式来为某些页建立哈希索引。
4. Log Buffer:日志缓冲区,用来保存要写入磁盘上log文件(Redo/Undo)的数据,日志缓冲区的内容定期刷新到磁盘log文件中。日志缓冲区满时会自动将其刷新到磁盘,当遇到BLOB或多行更新的大事务操作时,增加日志缓冲区可以节省磁盘I/O。
LogBuffer主要是用于记录InnoDB引擎日志,在DML操作时会产生Redo和Undo日志。
InnoDB磁盘主要包含Tablespaces,InnoDB Data Dictionary,Doublewrite Buffer、Redo Log和Undo Logs
InnoDB数据字典由内部系统表组成,这些表包含用于查找表、索引和表字段等对象的元数据。元数据物理上位于InnoDB系统表空间中。由于历史原因,数据字典元数据在一定程度上与InnoDB表元数据文件(.frm文件)中存储的信息重叠
位于系统表空间,是一个存储区域。在BufferPage的page页刷新到磁盘真正的位置前,会先将数据存在Doublewrite缓冲区。如果在page页写入过程中出现操作系统、存储子系统或mysqld进程崩溃,InnoDB可以在崩溃恢复期间从Doublewrite 缓冲区中找到页面的一个好备份。在大多数情况下,默认情况下启用双写缓冲区,要禁用Doublewrite缓冲区,可以将innodb_doublewrite设置为0。使用Doublewrite缓冲区时建议将innodb_flush_method设置为O_DIRECT
MySQL的innodb_flush_method这个参数控制着innodb数据文件及redo log的打开、刷写模式。有三个值:fdatasync(默认),O_DSYNC,O_DIRECT。设置O_DIRECT表示数据文件写入操作会通知操作系统不要缓存数据,也不要用预读,直接从Innodb Buffer写到磁盘文件。
重做日志是一种基于磁盘的数据结构,用于在崩溃恢复期间更正不完整事务写入的数据。
MySQL以循环方式写入重做日志文件,记录InnoDB中所有对Buffer Pool修改的日志。当出现实例故障(像断电),导致数据未能更新到数据文件,则数据库重启时根据Redo Log重新把数据更新到数据文件。读写事务在执行的过程中,都会不断的产生redo log。默认情况下,重做日志在磁盘上由两个名为ib_logfile0和ib_logfile1的文件物理表示
撤消日志是在事务开始之前保存的被修改数据的备份,用于例外情况时回滚事务。撤消日志属于逻辑日志,根据每行记录进行记录。撤消日志存在于系统表空间、撤消表空间和临时表空间中。
Master Thread是InnoDB的主线程,负责调度其他线程,优先级最高。作用是将缓冲池中的数据异步刷新到磁盘,保证数据的一致性。包含:脏页的刷新(page cleaner thread)、undo页回收(purge thread)、redo日志刷新(log thread)、合并写缓冲等。
在InnoDB中使用了大量的AIO来做读写处理,这样可以极大提高数据库的性能。一共10个线程。
- read thread : 负责读取操作,将数据从磁盘加载到缓存page页。4个
- write thread:负责写操作,将缓存脏页刷新到磁盘。4个
- log thread:负责将日志缓冲区内容刷新到磁盘。1个
- insert buffer thread :负责将写缓冲内容刷新到磁盘。1个
事务提交之后,其使用的undo日志将不再需要,因此需要Purge Thread回收已经分配的undo页。
作用是将脏数据刷新到磁盘,脏数据刷盘后相应的redo log也就可以覆盖,即可以同步数据,又能达到redo log循环使用的目的。会调用write thread线程处理。
InnoDB数据文件存储结构分为一个ibd数据文件-->Segment(段)-->Extent(区)-->Page(页)-->Row(行)
表空间,用于存储多个ibd数据文件,用于存储表的记录和索引。一个文件包含多个段。
段,用于管理多个Extent,分为数据段、索引段、回滚段。一个表至少有两个segment,一个管理索引,一个管理数据。
区,一个区固定包含64个连续的页,大小为1M。当表空间不足,需要分配新的页资源,不会一页页的分,直接分配一个区
页,用于存储多个Row行记录,大小为16K。包含很多种页类型,比如数据页、undo页、系统页、事务数据页、大的BLOB对象页。
行,包含了记录的字段值、事务ID、回滚指针、字段指针等信息。
Undo Log、Redo Log和Binlog
数据库事务开始前,会将要修改的记录放到Undo日志里,当事务要回滚或数据库崩溃时,撤销对未提交的事务对数据库产生的影响。
Undo Log产生和销毁:Undo Log在事务开始前产生;事务在提交时,并不会立刻删除Undo log,innodb会将该事务对应的Undo log放入到删除列表中,后面会通过后台线程purge thread进行回收处理。Undo Log属于逻辑日志,记录一个变化过程。例如执行一个delete,undolog会记录一个insert;执行一个update,undolog会记录一个相反的update。
show variables like '%innodb_undo%';
Undo Log的作用:
事务中修改的任何数据,将最新的数据备份存储到Redo Log里。Redo Log 是为了实现事务的持久性而出现的产物。防止在发生故障的时间点,尚有脏页未写入表的IBD文件中,在重启MySQL服务的时候,根据 Redo Log进行重做,将未入磁盘数据进行持久化。
Redo Log 的生成和释放:随着事务操作的执行,就会生成Redo Log,在事务提交时会将产生Redo Log写入Log Buffer,并不是随着事务的提交就立刻写入磁盘文件。等事务操作的脏页写入到磁盘之后,Redo Log 的使命也就完成了,Redo Log占用的空间就可以重用(被覆盖写入)
Redo Buffer 持久化到 Redo Log 的策略,可通过Innodb_flush_log_at_trx_commit 设置:
一般建议选择取值2,因为 MySQL挂了数据没有损失,整个服务器挂了才会损失1秒的事务提交数据。
3. Binlog(Binary log(二进制日志))
BinLog和上面的两种日志不同,他说属于Mysql Server的日志,不是InnoDb引擎特有的。Binlog是记录所有数据库表结构变更以及表数据修改的二进制日志。不会记录select这类操作。Binlog日志是以事件形式记录,还包含语句所执行的消耗时间。开启Binlog日志有以下两个最重要的使用场景。
Binlog文件名默认为“主机名_binlog-序列号”格式,例如oak_binlog-000001,也可以在配置文件中指定名称。文件记录模式有STATEMENT、ROW和MIXED三种,具体含义如下:
ROW(row-based replication,RBR):日志中会记录每一行数据被修改的情况,然后在slave端对相同的数据进行修改。
优点:能清楚记录每一个数据的修改细节,实现主从完全的同步和数据恢复
批量的操作会产生大量日志,如:alter table
STATMENT(statement-based replication,SBR):每一条被修改数据的SQL都会记录到master的Binlog中,slave在复制的时候SQL进程会解析成和原来master端执行过的相同的SQL再次执行。简称SQL语句复制
优点:日志量少,减少磁盘IO
缺点:在某些情况下会导致主从数据不一致,如last_insert_id()、now()等函数的执行。
MIXED(mixed-based replication,MBR):以上两种模式的混合使用,一般会使用STATEMENT模式保存Binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存Binlog,MySQL会根据执行的SQL语句选择写入模式。
Binlog文件操作命令
SHOW VARIABLES LIKE 'log_bin';
开启Binlog
需要修改my.cnf或my.ini配置文件,在[mysqld]下面增加log_bin=mysql_bin_log,重启MySQL服务。
使用show binlog events命令
show binary logs; //等价于show master logs;
show master status;
show binlog events;
show binlog events in 'mysqlbinlog.000001';
mysqlbinlog "文件名"
mysqlbinlog "文件名" > "test.sql"
mysqldump:定期全部备份数据库数据。mysqlbinlog可以做增量备份和恢复操作。
//按指定时间恢复
mysqlbinlog --start-datetime="2020-04-25 18:00:00" --stop-
datetime="2020-04-26 00:00:00" mysqlbinlog.000002 | mysql -uroot -p1234
//按事件位置号恢复
mysqlbinlog --start-position=154 --stop-position=957 mysqlbinlog.000002
| mysql -uroot -p1234
purge binary logs to 'mysqlbinlog.000001'; //删除指定文件
purge binary logs before '2020-04-28 00:00:00'; //删除指定时间之前的文件
reset master; //清除所有文件
可以通过设置expire_logs_days参数来启动自动清理功能。默认值为0表示没启用。设置为1表示超出1天binlog文件会自动删除掉。
Redo Log和Binlog的区别
书山有路勤为径,学海无涯苦作舟
目前我正在构建相当大的网络系统,我需要强大的 SQL 数据库解决方案。我选择 Mysql 而不是 Postgres,因为一些任务需要只读(MyISAM 引擎)而其他任务需要大量写入(InnoDB)。
我在 mysql 中使用如下命令。当它显示表格数据时,它被格式化为一个非常干净的表格,间距均匀且 |作为列分隔符。 SELECT * FROM TABLE_NAME; 当我从 CLI 运行命令时,如下
我知道这个问题之前已经被问过好几次了,我已经解决了很多问题,但到目前为止没有任何效果。 MySQL 试图将自身安装到的目录 (usr/local/mysql) 肯定有问题。关于我的错误的奇怪之处在于我
以下是我的 SQL 数据结构,我正在尝试如下两个查询: Select Wrk_ID, Wrk_LastName, Skill_Desc from Worker, Skill where
我们有一个本地 mysql 服务器(不在公共(public)域上),并希望将该服务器复制到我们拥有的 google 云 sql 实例。我的问题是:1.这可能吗?2.我们的本地服务器只能在本地网络上访问
我有一个表(test_table),其中一些字段值(例如字段 A、B 和 C)是从外部应用程序插入的,还有一个字段(字段 D),我想从现有表(store_table)插入其值,但在插入前者(A、B 和
我想创建一个 AWS RDS 实例,然后使用 terraform 管理数据库用户。因此,首先,我创建了一个 RDS 实例,然后使用创建的 RDS 实例初始化 mysql 提供程序,以进一步将其用于用户
当用户在我的网站上注册时,他们会在我的一个数据库中创建自己的表格。该表存储用户发布的所有帖子。我还想做的是也为他们生成自己的 MySql 用户——该用户仅有权从他们的表中读取、写入和删除。 创建它应该
我有一个关于 ColdFusion 和 Mysql 的问题。我有两个表:PRODUCT 和 PRODUCT_CAT。我想列出包含一些标记为:IS_EXTRANET=1 的特殊产品的类别。所以我写了这个
我想获取 recipes_id 列的值,以获取包含 ingredient_id 的 2,17 和 26 条目的值。 假设 ingredient_id 2 丢失则不获取记录。 我已经尝试过 IN 运算符
在 Ubuntu 中,我通常安装两者,但 MySQL 的客户端和服务器之间有什么区别。 作为奖励,当一个新语句提到它需要 MySQL 5.x 时,它是指客户端、服务器还是两者兼而有之。例如这个链接ht
我重新访问了我的数据库并注意到我有一些 INT 类型的主键。 这还不够独特,所以我想我会有一个指导。 我来自微软 sql 背景,在 ssms 中你可以 选择类型为“uniqeidentifier”并自
我的系统上有 MySQL,我正在尝试确定它是 Oracle MySQL 还是 MySQL。 Oracle MySQL 有区别吗: http://www.oracle.com/us/products/m
我是在生产 MySQL 中运行的应用程序的新维护者。之前的维护者已经离开,留下的文档很少,而且联系不上了。 我面临的问题是执行以下请求大约需要 10 秒: SELECT COUNT(*) FROM `
我有两个位于不同机器上的 MySQL 数据库。我想自动将数据从一台服务器传输到另一台服务器。比方说,我希望每天早上 4:00 进行数据传输。 可以吗?是否有任何 MySQL 内置功能可以让我们做到这一
有什么方法可以使用 jdbc 查询位于 mysql 根目录之外的目录中的 mysql 表,还是必须将它们移动到 mysql 根目录内的数据库文件夹中?我在 Google 上搜索时没有找到任何东西。 最
我在 mysql 数据库中有两个表。成员和 ClassNumbers。两个表都有一个付费年份字段,都有一个代码字段。我想用代码数字表中的值更新成员表中的付费年份,其中成员中的代码与 ClassNumb
情况:我有 2 台服务器,其中一台当前托管一个实时 WordPress 站点,我希望能够将该站点转移到另一台服务器,以防第一台服务器出现故障。传输源文件很容易;传输数据库是我需要弄清楚如何做的。两台服
Phpmyadmin 有一个功能是“复制数据库到”..有没有mysql查询来写这个函数?类似于将 db A 复制到新的 db B。 最佳答案 首先创建复制数据库: CREATE DATABASE du
我有一个使用 mySQL 作为后端的库存软件。我已经在我的计算机上对其进行了测试,并且运行良好。 当我在计算机上安装我的软件时,我必须执行以下步骤: 安装 mySQL 服务器 将用户名指定为“root
我是一名优秀的程序员,十分优秀!