MySQL -- 索引
索引模型哈希表实现上类似于java.util.HashMap,哈希表适合只有等值查询的场景
有序数组有序数组只适用于静态存储引擎(针对不会再修改的数据)
查找
等值查询:可以采用二分法,时间复杂度为O(log(N))
范围查询:查找[ID_card_X,ID_card_Y]
首先通过二分法找到第一个大于等于ID_card_X的记录
然后向右遍历,直到找到第一个大于ID_card_Y的记录
更新在中间插入或删除一个纪录就得挪动后面的所有的记录
搜索树平衡二叉树查询的时间复杂度:O(log(N)),更新的时间复杂度:O(log(N))(维持树的平衡)
N叉树
大多数的数据库存储并没有采用二叉树,原因:索引不仅仅存在于内存中,还要写到磁盘上
对于有100W节点的平衡二叉树,树高为20,即一次查询可能需要访问20个数据块
假设HDD,随机读取一个数据块需要10ms左右的寻址时间
即一次查询可能需要200ms – 慢成狗
为了让一个查询尽量少的读取磁盘,就必须让查询过程访问尽量少的数据块,因此采用N叉树
N的大小取决于数据页的大小和索引大小
在InnoDB中,以INT(4 Bytes)字段为索引,假设页大 ...
MySQL -- 事务隔离
概念
事务:保证一组数据库操作,要么全部成功,要么全部失败
在MySQL中,事务支持是在存储引擎层实现的
MyISAM不支持事务
InnoDB支持事务
隔离性与隔离级别
事务特性:ACID(Atomicity、Consistency、Isolation、Durability)
如果多个事务并发执行时,就可能会出现脏读、不可重复读、幻读(phantom read)等问题
解决方案:隔离级别
隔离级别越高,效率就会越低
SQL标准的事务隔离级别
READ-UNCOMMITTED
一个事务还未提交时,它所做的变更能被别的事务看到
READ-COMMITTED
一个事务提交之后,它所做的变更才会被其他事务看到
REPEATABLE-READ
一个事务在执行过程中所看到的数据,总是跟这个事务在启动时看到的数据是一致的
同样,在RR隔离级别下,未提交的变更对其他事务也是不可见的
SERIALIZABLE
对同一行记录,写会加写锁,读会加读锁,锁级别是行锁
当出现读写锁冲突时,后访问的事务必须等前一个事务执行完成,才能继续执行
默认隔离级别
Oracle:READ-COMMITTED
My ...
MySQL -- redolog + binlog
更新语句123mysql> CREATE TABLE T (id INT PRIMARY KEY, c INT);mysql> UPDATE T SET c=c+1 WHERE id=2;
执行过程
通过连接器,客户端与MySQL建立连接
update语句会把T表上的所有查询缓存清空
分析器会通过词法分析和语法分析识别这是一条更新语句
优化器会决定使用id这个索引(聚簇索引)
执行器负责具体执行,找到匹配的一行,然后更新
更新过程中还会涉及redolog(重做日志)和binlog(归档日志)的操作
redolog – InnoDB
如果每次更新操作都需要直接写入磁盘(在磁盘中找到相关的记录并更新),整个过程的IO成本和查找成本都很高
针对这种情况,MySQL采用的是WAL技术(Write-Ahead Logging):_先写日志,再写磁盘_
当有一条记录需要更新的时候,InnoDB会先把记录写到redolog(redolog buffer),并更新内存(buffer pool)
InnoDB会在适当的时候(例如系统空闲),将这个操作记录到磁盘里面(刷脏页)
InnoDB的redo ...
MySQL -- 基础架构
查询语句1mysql> select * from T where ID=10;
基本架构
大体上,MySQL可以分为Server层和存储引擎层
Server层包括连接器、查询缓存、分析器、优化器和执行器等
涵盖MySQL的大多数核心服务功能,以及所有的内置函数
所有的跨存储引擎的功能都在这一层实现,例如存储过程、触发器和视图等
存储引擎层负责数据的存储和提取,架构模式为插件式
支持InnoDB、MyISAM和Memory等存储引擎
最常用为InnoDB(Since 5.5.5,默认)
连接器连接器负责跟客户端建立连接、获取权限、维持和管理连接,命令如下
1$ mysql -h$host -P$port -u$user -p
权限
mysql是客户端工具,用来与服务端建立连接
在完成TCP三次握手之后,连接器就要开始认证身份,即-u和-p
如果账号密码不对,客户端会收到Access denied for user的错误
如果账号密码认证通过,连接器会到权限表里查询拥有的权限
之后在这个连接里的权限判断,都依赖于此时读取的权限
因此即使用管理员账号对权限进行修改,也不会影响到已经存 ...
JVM进阶 -- 浅谈Java Agent
Java Agent的运行方式
JVM并不会限制Java Agent的数量
可以在JVM参数中包含多个-javaagent参数
也可以远程attach多个Java Agent
JVM会按照参数的顺序或者attach的顺序,逐个执行Java Agent
JRebal/Btrace/arthas等工具都是基于Java Agent实现的
premain以JVM参数(-javaagent)的方式启动,在Java程序的main方法执行之前执行
MyAgent12345678package me.zhongmingmao;public class MyAgent { // JVM能识别的premain方法接收的是字符串类型的参数,并非类似main方法的字符串数组 public static void premain(String args) { System.out.println("premain"); }}
manifest.txt12345678910# 写入两行数据,最后一行为空行$ ech ...
JVM进阶 -- 浅谈JNI
native方法123public class Object { public native int hashCode();}
当Java代码调用native方法时,JVM将通过JNI,调用至对应的C函数Object.hashCode()就是一个native方法,对应的C函数将计算对象的哈希值,并缓存在对象头、栈上锁记录(轻量级锁)或者对象监视锁(重量级锁,monitor)中,以确保该值在对象的生命周期之内不会变更
链接方式在调用native方法之前,JVM需要将该native方法链接至对应的C函数上
自动链接JVM自动查找符合默认命名规范的C函数,并且链接起来
Java代码12345678package me.zhongmingmao.advanced.jni;public class Foo { int i = 0xDEADBEEF; public static native void foo(); public native void bar(int i, long j); public native void bar(String s, ...
JVM进阶 -- MAT
概念Shallow Heap + Retained HeapShallow HeapShallow heap is the memory consumed by one object. An object needs 32 or 64 bits (depending on the OS architecture) per reference, 4 bytes per Integer, 8 bytes per Long, etc. Depending on the heap dump format the size may be adjusted (e.g. aligned to 8, etc…) to model better the real consumption of the VM.
Retained SetRetained set of X is the set of objects which would be removed by GC when X is garbage collected.
Retained HeapRetained heap of X is the sum of shallo ...
JVM进阶 -- JDK命令
jpsLists the instrumented Java Virtual Machines (JVMs) on the target system.如果Java进程关闭了默认开启的UsePerfData参数(**-XX:-UsePerfData),那么jps/jstat将无法探知**到该Java进程
123$ jps1408 Jps19 LiveCoverMain
参数
备注
m
Displays the arguments passed to the main method. The output may be null for embedded JVMs.
l
Displays the full package name for the application’s main class or the full path name to the application’s JAR file.
v
Displays the arguments passed to the JVM.
jstatMonitors Java Virtual Machine (JVM) sta ...
JVM进阶 -- 浅谈注解处理器
注解与注解处理器
注解是Java 5引入,用来为类、方法、字段和参数等Java结构提供额外信息的机制
@Override仅对Java编译器有用,为Java编译器引用一条新的编译规则,编译完成后,它的使命也结束了
Java的注解机制允许开发人员自定义注解,这些自定义注解同样可以为Java编译器添加编译规则
这种功能需要由开发人员提供,并且以插件的形式接入Java编译器中,这些插件被称之为注解处理器
除了引入新的编译规则外,注解处理器还可以用于修改已有的Java源文件(不推荐)和生成新的Java源文件
123456789@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE)public @interface Override {}// 元注解@Target:用来限定目标注解所能标注的Java结构// 元注解@Retention:用来限定目标注解的生命周期// SOURCE:源代码,一旦源代码被编译为字节码,注解便会被擦除// CLASS:源代码+字节码// RUNTIME:源代码+字节码+运 ...
JVM进阶 -- 浅谈循环优化
循环无关代码外提外提无关代码
循环无关代码:循环中值不变的表达式
在不改变程序语义的情况下,将循环无关代码提出循环外
那么程序将避免重复执行这些表达式,从而达到性能提升的效果
1234567int foo(int x, int y, int[] a) { int sum = 0; for (int i = 0; i < a.length; i++) { sum += x * y + a[i]; } return sum;}
123456789101112131415161718192021222324252627// 对应的字节码int foo(int, int, int[]); Code: 0: iconst_0 1: istore 4 3: iconst_0 4: istore 5 6: goto 25// 循环体开始 9: iload 4 // load sum 11: iload_1 // load x 12: ilo ...