404 Not Found

Personal Notes


  • 首页

  • 归档

  • 标签

  • 搜索

MySQL 幻读与间隙锁

发表于 Apr 14 2019

这篇文章是学习极客时间专栏《MySQL 实战 45 讲》的笔记,加上我个人的一些理解,具体细节可以去读这个专栏。我们知道行锁只能锁住已经存在的行,并不能阻止插入新的行,如果同一个事务的两次查询中间其他事务插入了新的行,后一次查询就可能看到前一次查询没有看到的行,这就是幻读(Phantom Read)。需要注意的是,在可重复读隔离级别下,普通的查询是快照读,不会看到其他事务插入的数据,只有当前读才可能出现幻读。

加锁规则

为了解决幻读的问题,InnoDB 存储引擎引入了间隙锁(Gap Lock),锁住的是两个值之间的间隙。与行锁不同的是,跟间隙锁存在冲突关系的是“往这个间隙中插入行”的操作,间隙锁之间是不存在冲突的。间隙锁和行锁合称 Next-Key Lock,每个 Next-Key Lock 都是一个前开后闭区间,下面是《MySQL 实战 45 讲》中总结的加锁规则“两个原则、两个优化和一个 Bug”:

  • 原则 1:加锁的基本单位是 Next-Key Lock
  • 原则 2:查询过程中访问到的对象才会加锁
  • 优化 1:索引上的等值查询,给唯一索引加锁时,Next-Key Lock 退化为行锁
  • 优化 2:索引上的等值查询,向右遍历且最后一个值不满足等值条件时,Next-Key Lock 退化为间隙锁
  • Bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止
阅读全文 »

MySQL 事务的隔离性

发表于 Apr 7 2019

最近在学习 MySQL 的原理,通过写文章梳理一下,先从最不熟悉的事务的隔离性开始。

逻辑架构

下图展示了 MySQL 的逻辑架构图,大致分为 Server 层和存储引擎层。Server 层包含 MySQL 大多数的核心服务,包括查询解析、分析、优化、缓存以及所有的内置函数(例如,日期、时间、数学和加密函数),所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。存储引擎层负责 MySQL 中数据的存储和提取,其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多种存储引擎,现在最常用的存储引擎是 InnoDB(从 MySQL 5.5.5 版本开始作为默认存储引擎)。

阅读全文 »

Lighttpd 之 fdevent 分析

发表于 Mar 1 2018

陈硕的《Linux 多线程服务端编程》一书中有这样一段描述:

在高性能的网络程序中,使用得最广泛的编程模型当属 “non-blocking IO + IO multiplexing”,即 Reactor 模式。在这种模型中,程序的基本结构是一个事件循环(event loop),以事件驱动(event-driven)和事件回调的方式实现业务逻辑。Reactor 模型的有优点很明显,编程不难,效率也不错,对于 IO 密集型应用是个不错的选择。Lighttpd 就是这样,它内部的 fdevents 结构十分精妙,值得学习。

就我了解,在高性能 Web 服务器中,Lighttpd 的应用并不是特别广泛,占据统治地位的是 Nginx。工作中基于 Lighttpd 开发很大程度上是由于历史技术选型的原因。不过,看过它的源码之后,发现在设计方面的确十分精妙,之前分析过它的 plugin 机制,这次就来分析一下它的 fdevents 结构。

阅读全文 »

Lighttpd 之 plugin 分析

发表于 Feb 20 2018

Lighttpd 是 一个安全,快速,标准,且非常灵活的 Web 服务器,并对高性能环境做了最佳化。通过编写定制化的插件(plugin)可以增强服务器的功能,如提供高性能的 API 服务等。Lighttpd 实际上可以看作一个封装良好的网络库,利用它提供的基础框架,可以方便地在插件中实现自己的业务逻辑。我在工作中通过编写 Lighttpd 插件实现过几个高性能的 API 服务,现在想要系统地分析一下 Lighttpd 插件的工作机制。直接看源码吧,plugin.h 文件中定义了插件的数据结构:

typedef struct {
size_t version;
buffer *name;

void *data;
void *lib;

void *(* init) ();

handler_t (* set_defaults) (server *srv, void *p_d);
handler_t (* cleanup) (server *srv, void *p_d);
handler_t (* handle_trigger) (server *srv, void *p_d);
handler_t (* handle_sighup) (server *srv, void *p_d);

handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d);
...
} plugin;

可以看到,除了开头定义了 version、name 等成员变量,后面定义了大量的函数指针(上面贴的代码已经省略了很多),其实在创建插件的实例后,它们会被赋值为对应实现函数的指针,这样就实现了类似 C++ 中“多态”的功能:在不同插件的实例上调用相同的函数,会有不同的行为,这个行为取决于插件对该函数的特定实现。这些函数指针其实类似 C++ 中的“虚函数指针”,不过这里在编译期就确定了要调用哪个函数,并没有在运行时查询“虚函数表”的过程。

阅读全文 »

MapReduce 之 Mapper 分析

发表于 Feb 16 2018

前面文章简单分析了 InputFormat,它其实是在 Mapper 中被调用来读取输入数据的,Mapper 类的定义相当简单直观,直接上源码(还是来自 Hadoop 2.7.3):

public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {

public abstract class Context implements MapContext<KEYIN,VALUEIN,KEYOUT,VALUEOUT> { }

protected void setup(Context context) throws IOException, InterruptedException { }

protected void map(KEYIN key, VALUEIN value, Context context) throws IOException, InterruptedException {
context.write((KEYOUT) key, (VALUEOUT) value);
}

protected void cleanup(Context context) throws IOException, InterruptedException { }

public void run(Context context) throws IOException, InterruptedException {
setup(context);
try {
while (context.nextKeyValue()) {
map(context.getCurrentKey(), context.getCurrentValue(), context);
}
} finally {
cleanup(context);
}
}

}
阅读全文 »
1…456…9
wind4869

wind4869

44 日志
12 标签
GitHub E-Mail
© 2014 - 2020 wind4869
由 Hexo 强力驱动
主题 - NexT.Pisces
0%