读 MySQL 源码再看 INSERT 加锁流程
读 MySQL 源码再看 INSERT 加锁流程有一个问题,我还是彻底被问蒙了。他的问题是这样的: 加了插入意向锁后,插入数据之前,此时执行了 select…lock in share mode 语句(没有取到待插入的值),然后插入了数据,下一次再执行 select…lock in share mode(不会跟插入意向锁冲突),发现多了一条数据,于是又产生了幻读。会出现这种情况吗? 这个问题初看上去很简单,在 RR 隔离级别下,假设要插入的记录不存在,如果先执行select…lock in share mode 语句,很显然会在记录间隙之间加上 GAP 锁,而 insert 语句首先会对记录加插入意向锁,插入意向锁和 GAP 锁冲突,所以不存在幻读;如果先执行 insert 语句后执行 select…lock in share mode 语句,由于 insert 语句在插入记录之后,会对记录加 X 锁,它会阻止 select…lock in share mode 对记录加 S 锁,所以也不存在幻读。两种情况如下所示: 先执行 INSERT 后执行 SELECT: 先执行 SE...
高并发场景下,到底先更新缓存还是先更新数据库?
高并发场景下,到底先更新缓存还是先更新数据库?1 在大型系统中,为了减少数据库压力通常会引入缓存机制,一旦引入缓存又很容易造成缓存和数据库数据不一致,导致用户看到的是旧数据。 为了减少数据不一致的情况,更新缓存和数据库的机制显得尤为重要,接下来带领大家踩踩坑。 Cache asideCache aside也就是旁路缓存,是比较常用的缓存策略。 (1)读请求常见流程 Cache aside 读请求 应用首先会判断缓存是否有该数据,缓存命中直接返回数据,缓存未命中即缓存穿透到数据库,从数据库查询数据然后回写到缓存中,最后返回数据给客户端。 (2)写请求常见流程 Cache aside 写请求 首先更新数据库,然后从缓存中删除该数据。 看了写请求的图之后,有些同学可能要问了:为什么要删除缓存,直接更新不就行了?这里涉及到几个坑,我们一步一步踩下去。 Cache aside踩坑Cache aside策略如果用错就会遇到深坑,下面我们来逐个踩。 踩坑一:先更新数据库,再更新缓存 如果同时有两个写请求需要更新数据,每个写请求都先更新数据库再更新缓存,在并发场景可能会出现数据不一致的情况。...
Java内存区域详解
如果没有特殊说明,都是针对的是 HotSpot 虚拟机。 本文基于《深入理解 Java 虚拟机:JVM 高级特性与最佳实践》进行总结补充。 常见面试题: 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄和直接指针两种方式) 前言对于 Java 程序员来说,在虚拟机自动内存管理机制下,不再需要像 C/C++程序开发程序员这样为每一个 new 操作去写对应的 delete/free 操作,不容易出现内存泄漏和内存溢出问题。正是因为 Java 程序员把内存控制权利交给 Java 虚拟机,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,那么排查错误将会是一个非常艰巨的任务。 运行时数据区域Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。 JDK 1.8 和之前的版本略有不同,我们这里以 JDK 1.7 和 JDK 1.8 这两个版本为例介绍。 JDK 1.7: JDK 1.8: 线程私有的: 程序计数器 虚拟...
JDK监控和故障处理工具总结
JDK 命令行工具这些命令在 JDK 安装目录下的 bin 目录下: jps (JVM Process Status): 类似 UNIX 的 ps 命令。用于查看所有 Java 进程的启动类、传入参数和 Java 虚拟机参数等信息; **jstat**(JVM Statistics Monitoring Tool): 用于收集 HotSpot 虚拟机各方面的运行数据; jinfo (Configuration Info for Java) : Configuration Info for Java,显示虚拟机配置信息; jmap (Memory Map for Java) : 生成堆转储快照; jhat (JVM Heap Dump Browser) : 用于分析 heapdump 文件,它会建立一个 HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果; jstack (Stack Trace for Java) : 生成虚拟机当前时刻的线程快照,线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合。 jps:查看所有 Java 进程jps(JVM Proce...
JVM垃圾回收详解(重点)
如果没有特殊说明,都是针对的是 HotSpot 虚拟机。 本文基于《深入理解 Java 虚拟机:JVM 高级特性与最佳实践》进行总结补充。 常见面试题: 如何判断对象是否死亡(两种方法)。 简单的介绍一下强引用、软引用、弱引用、虚引用(虚引用与软引用和弱引用的区别、使用软引用能带来的好处)。 如何判断一个常量是废弃常量 如何判断一个类是无用的类 垃圾收集有哪些算法,各自的特点? HotSpot 为什么要分为新生代和老年代? 常见的垃圾回收器有哪些? 介绍一下 CMS,G1 收集器。 Minor Gc 和 Full GC 有什么不同呢? 前言当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。 堆空间的基本结构Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配。同时,Java 自动内存管理最核心的功能是 堆 内存中对象的分配与回收。 Java 堆是垃圾收集器管理的主要区域,因此也被称作 GC 堆(Garbage Collected Heap)。 从垃圾回收的角度来说,由于现在收集器基本都采用...
JVM线上问题排查和性能调优案例
JVM 线上问题排查和性能调优也是面试常问的一个问题,尤其是社招中大厂的面试。 这篇文章,我会分享一些我看到的相关的案例。 下面是正文。 一次线上 OOM 问题分析 - 艾小仙 - 2023 现象:线上某个服务有接口非常慢,通过监控链路查看发现,中间的 GAP 时间非常大,实际接口并没有消耗很多时间,并且在那段时间里有很多这样的请求。 分析:使用 JDK 自带的jvisualvm分析 dump 文件(MAT 也能分析)。 建议:对于 SQL 语句,如果监测到没有where条件的全表查询应该默认增加一个合适的limit作为限制,防止这种问题拖垮整个系统 资料:实战案例:记一次 dump 文件分析历程转载 - HeapDump - 2022。 生产事故-记一次特殊的 OOM 排查 - 程语有云 - 2023 现象:网络没有问题的情况下,系统某开放接口从 2023 年 3 月 10 日 14 时许开始无法访问和使用。 临时解决办法:紧急回滚至上一稳定版本。 分析:使用 MAT (Memory Analyzer Tool)工具分析 dump 文件。 建议:正常情况下,-Xmn参数(...
大白话带你认识 JVM
来自说出你的愿望吧丷投稿,原文地址:https://juejin.im/post/5e1505d0f265da5d5d744050 。 前言如果在文中用词或者理解方面出现问题,欢迎指出。此文旨在提及而不深究,但会尽量效率地把知识点都抛出来 一、JVM 的基本介绍JVM 是 Java Virtual Machine 的缩写,它是一个虚构出来的计算机,一种规范。通过在实际的计算机上仿真模拟各类计算机功能实现··· 好,其实抛开这么专业的句子不说,就知道 JVM 其实就类似于一台小电脑运行在 windows 或者 linux 这些操作系统环境下即可。它直接和操作系统进行交互,与硬件不直接交互,而操作系统可以帮我们完成和硬件进行交互的工作。 1.1 Java 文件是如何被运行的比如我们现在写了一个 HelloWorld.java 好了,那这个 HelloWorld.java 抛开所有东西不谈,那是不是就类似于一个文本文件,只是这个文本文件它写的都是英文,而且有一定的缩进而已。 那我们的 JVM 是不认识文本文件的,所以它需要一个 编译 ,让其成为一个它会读二进制文件的 HelloW...
最重要的JVM参数总结
本文由 JavaGuide 翻译自 https://www.baeldung.com/jvm-parameters,并对文章进行了大量的完善补充。 JDK 版本:1.8 1.概述在本篇文章中,你将掌握最常用的 JVM 参数配置。 2.堆内存相关 Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。 2.1.显式指定堆内存–Xms和-Xmx与性能有关的最常见实践之一是根据应用程序要求初始化堆内存。如果我们需要指定最小和最大堆大小(推荐显示指定大小),以下参数可以帮助你实现: 12-Xms<heap size>[unit]-Xmx<heap size>[unit] heap size 表示要初始化内存的具体大小。 unit 表示要初始化内存的单位。单位为**“ g”** (GB)、**“ m”(MB)、“ k”**(KB)。 举个栗子 🌰,如果我们要为 JVM 分配最小 2 GB 和最大 5 GB 的堆内存大小,...
类加载器详解
回顾一下类加载过程开始介绍类加载器和双亲委派模型之前,简单回顾一下类加载过程。 类加载过程:加载->连接->初始化。 连接过程又可分为三步:验证->准备->解析。 加载是类加载过程的第一步,主要完成下面 3 件事情: 通过全类名获取定义此类的二进制字节流 将字节流所代表的静态存储结构转换为方法区的运行时数据结构 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口 类加载器类加载器介绍类加载器从 JDK 1.0 就出现了,最初只是为了满足 Java Applet(已经被淘汰) 的需要。后来,慢慢成为 Java 程序中的一个重要组成部分,赋予了 Java 类可以被动态加载到 JVM 中并执行的能力。 根据官方 API 文档的介绍: A class loader is an object that is responsible for loading classes. The class ClassLoader is an abstract class. Given the binary name of a class, a ...
类加载过程详解
类的生命周期类从被加载到虚拟机内存中开始到卸载出内存为止,它的整个生命周期可以简单概括为 7 个阶段::加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)。其中,前三个阶段可以统称为连接(Linking)。 这 7 个阶段的顺序如下图所示: 类加载过程Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚拟机是如何加载这些 Class 文件呢? 系统加载 Class 类型的文件主要三步:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析。 详见 Java Virtual Machine Specification - 5.3. Creation and Loading。 加载类加载过程的第一步,主要完成下面 3 件事情: 通过全类名获取定义此类的二进制字节流。 将字节流所代表的静态存储结构转换为方法区的运行时数据结构。 在内存中生成一个代表该类的 Class 对象,作为方法区...
类文件结构详解
回顾一下字节码在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。 Clojure(Lisp 语言的一种方言)、Groovy、Scala、JRuby、Kotlin 等语言都是运行在 Java 虚拟机之上。下图展示了不同的语言被不同的编译器编译成.class文件最终运行在 Java 虚拟机之上。.class文件的二进制格式可以使用 WinHex 查看。 可以说.class文件是不同的语言在 Java 虚拟机之间的重要桥梁,同时也是支持 Java 跨平台很重要的一个原因。 Class 文件结构总结根据 Java 虚拟机规范,Class 文件通过 ClassFile 定义,有点类似 C 语言的结构体。 ClassFile 的结构如下: 123456...
测试文章
大家好! 我很高兴在这个美妙的虚空之字的博客世界里与大家相遇。这是我写博客的开端,也是我开始探索代码艺术之旅的起点。 代码,对我而言,不仅仅是冰冷的指令和函数的堆砌。它们如同音符,在我的手指间奏响优美的旋律。通过编码,我可以创造出令人惊叹的应用程序、网站和工具,将想法变为现实。 在这个博客中,我将分享我对代码的热爱和探索,以及与之相关的艺术与创造力。我会探讨编程的美妙之处,探索代码中隐藏的诗意,并分享我的创作心得和技巧。 我希望这个博客能成为一个交流和学习的平台,让我们共同探索代码艺术的无限可能。我鼓励大家在评论区留下你们的想法、问题和建议。我期待与你们的互动,共同成长。 让我们开始这个令人兴奋的旅程吧!感谢你们的支持和关注。 愿代码之旅带给我们无尽的创造和惊喜!
