<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[三易专栏]]></title><description><![CDATA[三易专栏]]></description><link>https://blog.youkuaiyun.com/liang_love_java</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; liang_love_java]]></copyright><item><title><![CDATA[Java基础之try catch finally的原理]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/122894655</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/122894655</guid><author>liang_love_java</author><pubDate>Sat, 12 Feb 2022 12:02:19 +0800</pubDate><description><![CDATA[先看一段代码

public class TestMain { public static int test() { int i = 0; try { System.out.println("业务执行"); // 标记1 i = 1 / 0; System.out.println("业务执行完成"); i++; return i; // 标记2 } catch (Exception e) { System.out.println("捕捉异常"); // 标记3 i++; return i; // 标记4 }]]></description><category></category></item><item><title><![CDATA[事务是怎样工作的]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/120073608</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/120073608</guid><author>liang_love_java</author><pubDate>Fri, 03 Sep 2021 08:36:16 +0800</pubDate><description><![CDATA[目录

事务特性

事务隔离性解决什么问题

隔离级别

事务隔离实现原理

可重复读隔离级别的实现原理

知识铺垫

InnoDB中的事务ID

数据的多版本（MVCC）

InnoDB 为每个事务构造了一个由事务ID组成的数组

一致性视图(read-view)

举例：可重复读的事务隔离级别工作原理

问答

问：回滚日志不会一直保留，什么时候删除

问：为什么尽量不要使用长事务

问：如何正确的开启事务

问：哪些操作会导致长事务，或者说如何避免长事务

问：如何查询数据库当前所有的事务

事务特性]]></description><category></category></item><item><title><![CDATA[join 是怎样工作的]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/120052933</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/120052933</guid><author>liang_love_java</author><pubDate>Thu, 02 Sep 2021 08:21:51 +0800</pubDate><description><![CDATA[目录

数据准备

Index Nested-Loop Join(NLJ)（扫描被驱动表用到索引）

Block Nested-Loop Join(BNL)（扫描被驱动表未用到索引）

假设 join bufer 足够大

实际中 join buffer 是有限制的

如何选择驱动表

走索引的情况

不走索引的情况

文中“小表”的含义

举例1

举例2

举例3

结论

Multi-Range Read（MRR）

Batched Key Access（BKA）

BNL 算法的性能问题

数据准备]]></description><category></category></item><item><title><![CDATA[group by 是怎样工作的]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/120029013</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/120029013</guid><author>liang_love_java</author><pubDate>Tue, 31 Aug 2021 23:10:25 +0800</pubDate><description><![CDATA[数据准备


CREATE TABLE `t2` (
  `id` int(11) NOT NULL,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_a` (`a`)
) ENGINE=InnoDB;

在表 t2 中插入数据 100 条数据
for(int i=1; i&lt;=100; i++) {
    insert into t2(id, a, b) values]]></description><category></category></item><item><title><![CDATA[order by 是怎样工作的]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119984326</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119984326</guid><author>liang_love_java</author><pubDate>Sun, 29 Aug 2021 19:36:35 +0800</pubDate><description><![CDATA[一图胜千言



rowid排序

排序的时候，只将 order by 后面排序字段以及记录主键放入到 sort buffer 中。比如 select a，b，c from t order by a desc，

只将字段a，表主键id 放入 sort buffer 中

全字段排序

排序的时候，将select sql中所有字段都放入到 sort buffer 中一起参与排序，无需根据rowid 再去主键索引上获取记录。

比如 select a，b，c from t order by a desc，只将]]></description><category></category></item><item><title><![CDATA[innodb存储引擎之：索引的数据结构]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119942690</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119942690</guid><author>liang_love_java</author><pubDate>Thu, 26 Aug 2021 23:25:49 +0800</pubDate><description><![CDATA[什么是 目录项

每个页对应一个目录项，每个目录项包括下面两个部分

页的用户记录中最小的主键值，用 key 来表示
	页号，用 page_Do 表示


主键索引结构示意图





二级索引结构示意图





联合索引结构示意图







InnoDB 中 B+ 树索引的注意事项

根节点千年不动窝

一个 B+ 树索引的根节点自创建之日起便不会再移动(也就是页号不再改变)。这样只要我们对某个表建立一个索引 ，那么它的根节点的页号便会被记录到某个地方，后续凡是 InnoDB 存储引擎需要用到这个索]]></description><category></category></item><item><title><![CDATA[更详细的执行计划 optimizer_trace]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119942563</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119942563</guid><author>liang_love_java</author><pubDate>Thu, 26 Aug 2021 23:21:00 +0800</pubDate><description><![CDATA[目录

数据准备

查看 optimizer_trace

数据准备


CREATE TABLE `t2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11),
  `b` int(11),
  `c` varchar(16) ,
  `create_time` datetime,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

插入数据
for(int i=1; i&]]></description><category></category></item><item><title><![CDATA[mysql是如何选择索引的（为什么会选错索引）]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119942328</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119942328</guid><author>liang_love_java</author><pubDate>Thu, 26 Aug 2021 23:12:24 +0800</pubDate><description><![CDATA[什么是查询成本

查询成本 = I/O成本 + CPU成本

I/O 成本：将数据从磁盘加载到内存的损耗时间称为 I/O 成本（对 memory 引擎的表除外，使用与磁盘性的存储引擎，例如 myisam，innodb）

CPU成本：读取记录，检测记录是否满足条件，对结果集进行排序等这些操作的损耗时间称为 CPU 成本



对Innodb 存储引擎来说，读取一个数据页花费的成本默认是 1.0；读取记录、检测记录是否满足条件成本默认是 0.2。这里说的 “1.0” “0.2”，在mysql中是可以设置的

]]></description><category></category></item><item><title><![CDATA[innodb存储引擎之：索引的数据结构（B+TREE）]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119919904</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119919904</guid><author>liang_love_java</author><pubDate>Wed, 25 Aug 2021 21:29:41 +0800</pubDate><description><![CDATA[什么是 目录项

每个页对应一个目录项，每个目录项包括下面两个部分

页的用户记录中最小的主键值，用 key 来表示
	页号，用 page_no 表示
主键索引结构示意图



二级索引结构示意图



联合索引结构示意图



InnoDB 中 B+ 树索引的注意事项

根节点千年不动窝

一个 B+ 树索引的根节点自创建之日起便不会再移动(也就是页号不再改变)。这样只要我们对某个表建立一个索引 ，那么它的根节点的页号便会被记录到某个地方，后续凡是 InnoDB 存储引擎需要用到这个索引时，都会从那个固定]]></description><category></category></item><item><title><![CDATA[innodb存储引擎之：innodb buffer pool]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119919753</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119919753</guid><author>liang_love_java</author><pubDate>Wed, 25 Aug 2021 21:20:32 +0800</pubDate><description><![CDATA[目录

缓冲页

缓冲页的控制块

缓冲页的哈希表

free 链表

flush 链表

LRU 链表

从 innodb buffer pool 看 select 语句的执行过程

多个 innodb buffer pool 实例

innodb_buffer_pool_chunk_size

查看 innodb buffer pool 状态信息

小小的扩展点

问答：

缓冲页

innodb buffer pool 将一块连续的内存划分成了，大小固定的缓冲页。一个缓冲页保存这一个数据页上的所有数据]]></description><category></category></item><item><title><![CDATA[innodb存储引擎之：表空间]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119887472</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119887472</guid><author>liang_love_java</author><pubDate>Tue, 24 Aug 2021 12:52:40 +0800</pubDate><description><![CDATA[概览

https://www.mubucm.com/doc/5X-MdVzKDKB







为什么innodb设计了“区”的概念

如果以页为单位来分配存储空间，B+树索引中同一层级的双向链表相邻的两个页之间的物理位置可能离得非常远，会导致遍历索引的时候，无法使用顺序I/O，所以引入了“区”的概念



为什么innodb设计了“碎片区”的概念

如果有些表的本身的记录数很少，例如业务配置类型的表，直接以“区”为单位分配存储空间，就会导致磁盘空间的浪费。所以mysql规定，当一个表占用的页数量超过.]]></description><category></category></item><item><title><![CDATA[innodb 存储引擎之：记录的数据结构，数据页的数据结构]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119879843</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119879843</guid><author>liang_love_java</author><pubDate>Mon, 23 Aug 2021 23:32:46 +0800</pubDate><description><![CDATA[目录

innodb 行格式

COMPACT 行格式

记录的额外信息

变长字段长度列表

NULL值列表

记录的头信息

记录的真实数据

innodb数据页结构示意图

File Header

Page Header（页头部）

lnfimum + Supremum

User Records

Free Space

Page Directory（页目录）

File Trailer

一个数据页的示意图

innodb 行格式

innodb 有4中不同类型的行格式，分别是

COMPACT]]></description><category></category></item><item><title><![CDATA[memory 存储引擎]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119879725</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119879725</guid><author>liang_love_java</author><pubDate>Mon, 23 Aug 2021 23:05:10 +0800</pubDate><description><![CDATA[目录

memory 引擎

memory 表结构示意图

memory表的特点

在memory表上创建 B-Tree 索引

为什么不建议在生产环境使用 memory 引擎的表

锁粒度

数据持久化问题

主从数据同步问题

在双M高可用架构中，更诡异的现象

memory 引擎

memory 表结构示意图





memory表的特点

Memory 引擎的数据和索引是分开的
	内存表的数据部分以数组的方式单独存放，而主键 id 索引里，存的是每个数据的位置（数组的下标）。主键 id 是 has]]></description><category></category></item><item><title><![CDATA[mysql 逻辑架构图概览]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/119867216</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/119867216</guid><author>liang_love_java</author><pubDate>Mon, 23 Aug 2021 13:16:57 +0800</pubDate><description><![CDATA[逻辑架构图



Server 层包括连接器、查询缓存、分析器、优化器、执行器等，涵盖 MySQL 的大多数核心服务功能，以及所有的内置函数（如日期、时间、数学和加密函数等），所有跨存储引擎的功能都在这一层实现，比如存储过程、触发器、视图等。



而存储引擎层负责数据的存储和提取。其架构模式是插件式的，支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB，它从 MySQL 5.5.5 版本开始成为了默认存储引擎。



连接器

管理链接，权限验证
	校验.]]></description><category></category></item><item><title><![CDATA[创建型-适配器模式]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/113888192</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/113888192</guid><author>liang_love_java</author><pubDate>Sat, 20 Feb 2021 17:43:00 +0800</pubDate><description><![CDATA[描述

这个模式就是用来做适配的，它将不兼容的接口转换为可兼容的接口，让原本由于接口不兼容而不能一起工作的类可以一起工作。对于这个模式，有一个经常被拿来解释它的例子，就是 USB 转接头充当适配器，把两种不兼容的接口，通过转接变得可以一起工作。



实现方式

类适配器，类适配器使用继承关系来实现
	对象适配器，对象适配器使用组合关系来实现
针对这两种实现方式，在实际的开发中，到底该如何选择使用哪一种呢？判断的标准主要

有两个，一个是 Adaptee 接口的个数，另一个是 Adaptee 和 ITar.]]></description><category></category></item><item><title><![CDATA[结构型-装饰器模式]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/113888150</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/113888150</guid><author>liang_love_java</author><pubDate>Sat, 20 Feb 2021 17:41:38 +0800</pubDate><description><![CDATA[描述

装饰器模式主要解决继承关系过于复杂的问题，通过组合来替代继承。它主要的作用是给原始类添加增强功能。这也是判断是否该用装饰器模式的一个重要的依据。

除此之外，装饰器模式还有一个特点，那就是可以对原始类嵌套使用多个装饰器。为了满足这个应用场景，在设计的时候，装饰器类需要跟原始类继承相同的抽象类或者接口。



代码示例

假设这样一个场景，根据 userId 获取用户数据。先从缓存中获取，如果缓存中没有，则从第三方获取并写入到缓存中。


			// 定义获取用户数据接口

			publicin..]]></description><category></category></item><item><title><![CDATA[结构型-桥接模式]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/113888132</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/113888132</guid><author>liang_love_java</author><pubDate>Sat, 20 Feb 2021 17:39:54 +0800</pubDate><description><![CDATA[将抽象和实现解耦，让它们可以独立变化。这里所说的“抽象”不是某个具体的抽象类或者接口，而是一类抽象类、接口或者说由多个抽象类、接口组成的这个“抽象”。而这里说的“实现”也是对“抽象”中的抽象类、接口的具体实现。

引用别人的一段话

桥接看着就像是面向接口编程这一原则的原旨—将实现与抽象分离。让我迷惑的是，让两者独立变化的说法，接口不是应该稳定吗，为什么要变化？
多个纬度独立变化那个解释倒是比较容易理解。文中举的警报的例子很贴切。紧急程度和警报的方式可以是两个不同的纬度。可以有不同的组合方式。
这与slf4]]></description><category></category></item><item><title><![CDATA[创建型-建造者模式]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/113887985</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/113887985</guid><author>liang_love_java</author><pubDate>Sat, 20 Feb 2021 17:33:54 +0800</pubDate><description><![CDATA[解决了什么问题

如果一个类中有很多属性，为了避免构造函数的参数列表过长，影响代码的可读性和易用性，我们可以通过构造函数配合 set() 方法来解决。但是，如果存在下面情况中的任意一种，我们就要考虑使用建造者模式了。

我们把类的必填属性放到构造函数中，强制创建对象的时候就设置。如果必填的属性有很多，把这些必填属性都放到构造函数中设置，那构造函数就又会出现参数列表很长的问题。如果我们把必填属性通过 set() 方法设置，那校验这些必填属性是否已经填写的逻辑就无处安放了。
	如果类的属性之间有一定的依赖关系或]]></description><category></category></item><item><title><![CDATA[创建型-原型模式]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/113887855</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/113887855</guid><author>liang_love_java</author><pubDate>Sat, 20 Feb 2021 17:28:53 +0800</pubDate><description><![CDATA[注意注意，原个毛线



是什么

如果对象的创建成本比较大，而同一个类的不同对象之间差别不大（大部分字段都相同），在这种情况下，我们可以利用对已有对象（原型）进行复制（或者叫拷贝）的方式来创建新对象，以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式（Prototype Design Pattern），简称原型模式。



实现方法

浅拷贝：只会复制对象中基本数据类型数据和引用对象的内存地址，不会递归地复制引用对象，以及引用对象的引用对象……而深拷贝得到的是一份完完全全独立的对..]]></description><category></category></item><item><title><![CDATA[结构型-代理模式]]></title><link>https://blog.youkuaiyun.com/liang_love_java/article/details/113887753</link><guid>https://blog.youkuaiyun.com/liang_love_java/article/details/113887753</guid><author>liang_love_java</author><pubDate>Sat, 20 Feb 2021 17:24:51 +0800</pubDate><description><![CDATA[解决什么问题

当需要在不修改一个类的前提下，对类的方法进行功能增强时，就需要使用代理模式。或者说 通过引入代理类来给原始类附加功能



应用场景

代理模式常用在业务系统中开发一些非功能性需求，比如：监控、统计、鉴权、限流、事务、幂等、日志。我们将这些附加功能与业务功能解耦，放到代理类统一处理，让程序员只需要关注业务方面的开发。除此之外，代理模式还可以用在 RPC、缓存等应用场景中。



如何实现的

静态代理，代理类


			// 原始类

			publicclassUser {

		...]]></description><category></category></item></channel></rss>