数据库
InnoDB, MyISM引擎区别
MyISAM 和 InnoDB 是 MySQL 数据库最常见的两种存储引擎,每种都有其优点和缺点。以下是它们之间的一些主要差异:
- 事务支持:InnoDB 支持事务(Transaction),而 MyISAM 不支持。事务是一种可以由 DBMS (数据库管理系统)访问并可能更新各种数据库表中数据的程序执行单元。MyISAM 在不支持事务的情况下,如果在写入过程中发生崩溃,可能会导致数据的不一致。
- 锁定机制:MyISAM 只支持表级锁定(table-level locking),而 InnoDB 还支持行级锁定(row-level locking)。行级锁定允许更高的并发性,尤其是在多用户并发读写的情况下。
- 数据完整性和外键:InnoDB 支持外键(foreign key)和参照完整性(referential integrity),这是实现级联删除和级联更新的重要功能。而 MyISAM 不支持。
- 存储空间:MyISAM 表的存储空间通常比 InnoDB 表的要小。这是因为 InnoDB 使用了更复杂的数据结构来支持事务和行级锁定。
- 全文索引:在 MySQL 5.6 版本之前,只有 MyISAM 支持全文索引(Full-text Search)。但从 MySQL 5.6 开始,InnoDB 也支持全文索引。
- 崩溃恢复:InnoDB 有更好的崩溃恢复能力。由于 MyISAM 不支持事务,因此在发生崩溃时,可能需要更多的手动干预来恢复数据。
在选择存储引擎时,需要根据应用的需求进行权衡。如果需要事务支持、崩溃恢复和高并发写入,那么应该选择 InnoDB。如果应用主要是只读的,或者需要全文索引(在 MySQL 5.6 之前的版本),那么可以使用 MyISAM。
默认级别如何处理幻读问题
小林Coding:
MySQL InnoDB 引擎的可重复读隔离级别(默认隔离级),根据不同的查询方式,分别提出了避免幻读的方案:
- 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读。
- 针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读。
我举例了两个发生幻读场景的例子。
第一个例子:对于快照读, MVCC 并不能完全避免幻读现象。因为当事务 A 更新了一条事务 B 插入的记录,那么事务 A 前后两次查询的记录条目就不一样了,所以就发生幻读。
第二个例子:对于当前读,如果事务开启后,并没有执行当前读,而是先快照读,然后这期间如果其他事务插入了一条记录,那么事务后续使用当前读进行查询的时候,就会发现两次查询的记录条目就不一样了,所以就发生幻读。
所以,MySQL 可重复读隔离级别并没有彻底解决幻读,只是很大程度上避免了幻读现象的发生。
要避免这类特殊场景下发生幻读的现象的话,就是尽量在开启事务之后,马上执行 select ... for update 这类当前读的语句,因为它会对记录加 next-key lock,从而避免其他事务插入一条新记录。
慢SQL的实现。MySQL本身的监控机制
慢查询日志:MySQL可以记录查询执行时间超过一定阈值的查询,这些查询被称为"慢查询"。你可以通过配置MySQL服务器来启用慢查询日志,并设置所需的阈值。
启用慢查询日志可以帮助你找出性能问题,因为你可以看到哪些查询需要花费很长时间来执行。然后,你可以使用
EXPLAIN
语句和其他优化技术来改进这些查询的性能。以下是如何启用和使用MySQL慢查询日志的一些步骤:
- 启用慢查询日志:你可以在MySQL配置文件 (通常是
my.cnf
或my.ini
) 中将slow_query_log
设置为ON
来启用慢查询日志。你也可以在运行中的MySQL服务器中动态地设置它:
- 设置慢查询阈值:你可以设置
long_query_time
系统变量来定义什么样的查询应该被记录在慢查询日志中。例如,如果你想记录所有运行时间超过1秒的查询,你可以这样设置:
- 设置慢查询日志文件:你还需要告诉MySQL将慢查询日志写入到哪个文件。你可以将
slow_query_log_file
系统变量设置为你想要的文件名:
一旦你配置并启用了慢查询日志,MySQL就会开始记录运行时间超过
long_query_time
的查询。然后,你可以定期检查这个日志,找出运行缓慢的查询,并尝试优化它们。需要注意的是,慢查询日志可能会占用大量磁盘空间,特别是在一个繁忙的系统中,或者当
long_query_time
被设置得很低时。因此,你应该定期旋转和/或清理慢查询日志,以防止它占用过多的磁盘空间。你也可以考虑只在需要进行性能调优时才启用慢查询日志。MySQL聚集索引和非聚集索引
在MySQL中,特别是在使用InnoDB存储引擎的情况下,索引可以分为两类:聚集索引和非聚集索引。
- 聚集索引(Clustered Index):在InnoDB中,表的数据按照主键的顺序存放,即按照聚集索引存放。因此,每个InnoDB表都有一个聚集索引。如果在创建表时没有明确指定主键,MySQL系统会寻找第一个非空的唯一索引作为主键,即作为聚集索引。如果表中没有这样的列,InnoDB会自动为每行生成一个6字节的ROWID,然后以此作为聚集索引。因为聚集索引决定了表中数据的物理存储顺序,所以一个表中只能有一个聚集索引。
- 非聚集索引(Non-Clustered Index,也被称为二级索引、辅助索引):非聚集索引是不包含所有数据的索引。非聚集索引包含索引的键值和一个指向每行数据实际位置的指针。在查找过程中,数据库首先找到索引,然后使用索引中的指针找到数据。非聚集索引的键值和实际数据存储是分开的,所以在一个表里可以有多个非聚集索引。
JAVA
JAVA Object,HashCode,equals
在Java中,
Object
是所有类的基类。每个类都默认继承了 Object
类,这意味着每个对象都有 Object
类的方法。其中最常被重写的两个方法就是 hashCode()
和 equals()
。1.
equals(Object obj)
方法:equals()
方法主要用来测试两个对象是否在逻辑上相等,也就是说,它们是否代表了相同的事物,不一定要是同一个对象。默认情况下,equals()
方法与 ==
操作符的行为完全相同,也就是说它检查两个对象是否是同一个对象。但在很多情况下,我们可能需要重写 equals()
方法,以便它可以根据我们自己的业务逻辑来判断两个对象是否相等。2.
hashCode()
方法:hashCode()
方法用于获取对象的哈希码,这个哈希码由对象的内存地址经过哈希函数计算得出。哈希码通常用于确定对象在哈希集合(例如 HashMap
、HashSet
等)中的存储位置。hashCode()
方法的默认行为是返回对象的内存地址。但和 equals()
方法一样,我们可以根据需要重写 hashCode()
方法。3.
equals()
和 hashCode()
的关系:当你重写
equals()
方法时,通常也需要重写 hashCode()
方法,以保持它们之间的一致性。也就是说,如果两个对象在 equals()
方法中被判断为相等,那么它们的 hashCode()
方法也应该返回相同的结果。反之,如果两个对象的 hashCode()
相同,那么它们并不一定相等,因为不同的对象可能会有相同的哈希码(这种情况被称为哈希冲突)。以下是一个简单的例子,展示了如何重写
equals()
和 hashCode()
方法:这个
Person
类重写了 equals()
和 hashCode()
方法。equals()
方法检查两个 Person
对象是否有相同的 name
和 age
。hashCode()
方法返回一个基于 name
和 age
的哈希码。java volatile
在Java中,
volatile
是一个关键字,用于修饰变量,以确保其在多线程环境中的可见性和顺序性。1. 可见性:
在多线程环境中,为了提高效率,每个线程都会有自己的工作内存(可以理解为CPU的高速缓存),线程对变量的所有操作都在自己的工作内存中进行,然后再将改变的值刷新到主内存中。因此,如果一个线程修改了一个变量的值,其他线程可能无法立即看到这个改变。如果一个变量被声明为
volatile
,JVM保证了每次读取该变量都将从主内存中进行,每次写入都将立即同步回主内存,从而保证了变量在多个线程间的可见性。2. 顺序性(即禁止指令重排序):
在执行程序时,为了提高性能,编译器和处理器可能会对指令进行重排序。但是,当变量被声明为
volatile
时,JVM会禁止对其相关的指令进行重排序,也就是说,所有在对volatile
变量进行写操作之前的操作都必须在写操作完成之前执行,所有在读操作之后的操作都必须在读操作完成之后执行。然而,需要注意的是,虽然
volatile
关键字可以保证单个读/写操作的原子性,但它不能保证复合操作(如i++
)的原子性。因此,如果需要对复合操作进行同步,你可能需要使用synchronized
关键字或java.util.concurrent
包中的一些类。以下是一个使用
volatile
关键字的简单示例:在这个例子中,
count
变量被声明为volatile
,这意味着在多线程环境中,所有线程都能够看到最新的count
值,而且对count
的读/写操作不会被指令重排序。但是,incrementCount
方法并不是线程安全的,因为count++
是一个复合操作。- 作者:Olimi
- 链接:https://olimi.icu/article/98d2d492-da0f-4dba-9bdb-d4b5e151e4e8
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。