数据库的三范式是什么?
数据库的三范式(
Three Normal Forms
)是一种设计规范用于规范化关系型数据库中的数据结构,以减少数据冗余和提高数据的一致性。
第一范式(1NF):
- 要求关系表中的每个属性都是原子的,不可再分。
- 也就是说,每个属性不能包含多个值或多个属性。
- 通过将多值属性拆分为单值属性,可以消除数据冗余和复杂性。
第二范式(2NF):
- 在满足1NF的基础上,要求表中的非主键属性完全依赖于主键。
- 换句话说,非主键属性必须完全依赖于候选键(主键)。
- 如果存在部分依赖,即一个非主键属性依赖于候选键的一部分属性,就需要将其拆分为独立的关系表。
第三范式(3NF):
- 在满足2NF的基础上,要求表中的非主键属性之间没有传递依赖关系。
- 如果存在传递依赖,即一个非主键属性依赖于另一个非主键属性,就需要将其拆分为独立的关系表。
什么是索引?
MySQL索引是一种数据结构,用于提高数据库查询的速度和效率。
- 它类似于书中的目录,可以帮助数据库系统快速定位到存储数据的位置,减少了数据库的扫描和比较操作。
在MySQL中,索引可以根据不同的列或列组合来创建。
当执行查询时,MySQL可以利用索引快速定位到满足查询条件的行,而不必扫描整个数据表。
- 这样可以提高查询的速度,并减少数据库的负载。
什么字段适合创建索引?
在MySQL中,创建索引的选择需要综合一下几个考虑:
常用作查询条件的字段:
- 如果表的某个列经常用于
where
子句中,为该列建立一个索引可以极大地提高查找速度。常用作连接的列:
- 如果一列经常出现在多表查询的关联条件里,为该列建索引一样可以提高效率。
在
ORDER BY, GROUP BY
或DISTINCT
中经常使用的列:
- 这能大大提升排序和分组等操作的速度。
区分度比较高的字段:
- 比如每个用户会有一个ID,显然每个用户的ID都是不一样的,这样的话,数据的区分度就很高,就适合做索引
- 但是想用户性别这种,只有男,女两种,基本没有啥区分度,那么不适合做索引。
什么字段不适合创建索引?
以下几种情况的字段不适合创建索引:
数据重复度高的字段:
- 字段的唯一性越好,索引性能越好。
- 如果字段中数据重复度高,那么这个字段就不适合创建索引。
- 比如:性别,只有男、女两个值,在几千万、几亿的数据表中,这个字段的重复度就非常高。
数据量小或者数据分布极为不均匀的字段:
- 如果表的记录非常少,或者表中的数据分布非常不均,索引将无法发挥效用。
经常改动的字段:
- 如果某列经常进行
insert、delete、update
操作,对这样的列建立索引
- 虽然可以提高查询速度,但同时也会降低更新速度。
不常用于查询条件的字段:
- 如果某个字段不常用于查询条件(
WHERE
子句中)
- 那么创建索引不但无法提升性能,反而会浪费磁盘空间。
索引的底层使用的是什么数据结构?
MySQL的索引底层主要使用了两种数据结构,分别是
B+Tree
索引和Hash索引。B+Tree索引:
- 大部分MySQL存储引擎的默认索引类型。
- B+Tree是一种平衡多路查找树,可以保证数据的有序性,并且有较高的查找效率。
- 比如InnoDB存储引擎就采用的
B+Tree
索引。
- 在
B+Tree
索引中,索引项是按照顺序排列并分布在树上的,这样对范围查询和排序就有了很大的优势。Hash索引:
- Memory存储引擎的索引就采用了Hash索引,适用于等值查询,但不支持范围查询和排序等操作。
Hash
索引的查询速度非常快,但是索引的维护成本较高,而且Hash冲突的存在也会影响查询性能。需要注意的是,还有其他类型的索引,例如空间数据索引(基于
R-Tree
的GIS空间索引),全文索引等
- 但是在底层使用最广泛的数据结构依然是
B+Tree
索引和Hash索引。
为什么 InnoDB 存储引擎选用 B+ 树而不是 B 树呢?
InnoDB存储引擎选择B+树作为索引结构,而非B树,主要出于以下几个原因:
磁盘I/O操作降低:
- B+树只需要遍历少数节点就可以找到需要的数据,
I/O
次数大大减少,降低了磁盘I/O操作。查询效率更稳定:
- B+树的每一个叶子节点存储了所有的键值,所有数据的查找必须从根节点开始进行,而不像B树那样
- 其搜索性能最好时可在顶端完成,最差则可能要寻找到叶子节点
- 因此,B+树的查询稳定性更好。
非叶子节点不存储数据,可以存储更多的键:
- 这意味着B+树的非叶子节点可以存储的键值数量更多,所以树的高度会更低,查询效率更高。
B+树的叶子节点都相连:
- 这对于范围查询极其有利。
- 如果你需要进行一个范围查询,你只需要找到范围的最小值
- 然后沿着叶子节点链表往后读就行了,直到遇到范围的最大值。
- 而如果你用B树的话,查找范围最小值和最大值是独立的,二者没有任何关系。
MySQL 索引分类有哪些?
在MySQL的InnoDB存储引擎中,大致可以将索引分为以下四类:
主键索引 (Primary Key):
- 主键索引是所有InnoDB表必须的,且一个表中只能有一个主键索引。
- sInnoDB的数据文件就是按照主键顺序存放的,也就是聚簇索引。
- 主键索引的选择对查询的性能有很大的影响。
唯一索引 (Unique Index):
- 唯一索引中的键值必须唯一,但允许有空值。如果是组合索引,则组合的值必须唯一。
普通索引 (Normal Index) 或非唯一索引:
- 这是最基本的索引,没有任何约束。
全文索引 (Fulltext Index):
- 主要用于全文搜索,即针对大文本进行的搜索。
- MySQL的InnoDB和MyISAM存储引擎都支持全文索引。
- 但是,InnoDB的全文索引在功能和性能上与MyISAM存在差距
- 如需对全文索引的性能要求较高,或者对全文索引的更高级功能有所要求,建议使用MyISAM存储引擎。
什么是覆盖索引?
覆盖索引(
Covering Index
)是指一个查询语句的执行只用从索引中就能获取到足够的信息
- 不需要再去实际的数据行中检索。
比如一个表中有100列,我们要查询某个字段的总和或者平均值,如果这个字段已经被索引了
- 那么查询时就只需要读取索引,而不需要访问表,这样就大大提升了查询性能。
例如,假设有一个用户表 USER,主键为
USER_ID
,以 EMAIL 和USERNAME
为索引。当你执行如下查询语句时:
SELECT EMAIL, USERNAME FROM USER WHERE EMAIL='test@example.com'
查询只需要读索引,因为索引已经包含了所有查询所需信息,即 EMAIL 和 USERNAME。
- 查询不需要查询实际的数据行,使其成为覆盖索引。
- 这样做可以大大提高查询效率,因为索引项大小一般远小于实际的行数据。
什么是联合索引?
联合索引(
Composite Index
)是基于两个或者更多列的索引。所谓的联合索引并不是单纯地将各个列上的索引组合起来,而是将几个列作为一个整体建立一个索引。
- 这样,数据库系统可以快速找到给定索引列的子集。
例如,假设我们有一个Person表,该表有三列:
FirstName,LastName和BirthDate
。如果我们经常需要查询具有特定姓和名的人,那么我们可以创建一个联合索引,如下所示:
CREATE INDEX index_name ON Person (LastName, FirstName)
这样,当执行如下查询时:
SELECT * FROM Person WHERE LastName='Doe' AND FirstName='John'
MySQL 将多次快速找到
LastName 为 ‘Doe’ 和 FirstName 为 ‘John’
的条目
- 因为它们在索引中一起存在。
联合索引遵循最左前缀原则,就是说如果联合索引有三个字段
(A,B,C)
那么你查
A,A,B
或A,B,C
时,都可以利用上这个索引。但查询单独B,B,C或者C并不能利用这个索引。
所以设立联合索引的顺序也很重要,需要根据查询的需求来排序。
什么情况下索引会失效?即查询不走索引?
在一些特定的情况下,即使表上存在索引,索引也可能不生效,不能被查询优化器使用。
以下是一些常见的情况:
使用
!=或<>
操作符:
- 索引对期待扫描全部数据的查询通常没有帮助,尤其是不等式查询。
对索引列进行计算或函数操作:
- 如果对一个索引列进行函数操作,那么引擎将无法使用索引,因为它必须对每个行执行函数操作后才能比较结果。
- 例如:
SELECT * FROM table WHERE YEAR(date_column) = 2022;
使用LIKE操作符以%开头的模糊查询:
- 当LIKE的模式值以通配符%开头时,无法使用索引,因为查询引擎无法知道搜索结果在何处开始或结束。
- 例如:
SELECT * FROM table WHERE column LIKE '%Z';
联合索引中使用最左前缀原则。
- 像
(col1, col2, col3)
这样的联合索引只有在查询条件在索引树左侧时才能够被用到。- 比如查询
col1
或col1, col2
,索引是起效的。- 但当查询
col2
或者col3
或者col2, col3
这样,该索引就不起作用了。数据类型不一致:
- 如果查询中的数据类型与索引中的数据类型不一致,MySQL将无法使用索引。
谈谈你对最左前缀原则的理解?
最左前缀原则是 MySQL 使用联合索引的一种重要原则
- 它决定了数据库可以如何利用索引进行查询优化。
联合索引是指一个索引包括多个列。
- 例如,你有一个表包含
last_name
和first_name
两列,你可以创建一个联合索引包含这两列。这个时候,最左前缀原则就发挥作用了。
根据该原则,你可以只通过该联合索引的最左部分进行搜索。
- 反过来说,如果你的查询不包含索引的最左部分,那么 MySQL 将无法利用该索引。
举个例子,假设有个联合索引
(last_name, first_name)
,以下查询可以利用到索引:
- 查询
last_name='Smith'
- 查询
last_name='Smith' AND first_name='John'
而以下查询则无法利用到索引:
- 查询
first_name='John'
虽然
first_name
是索引的一部分,但它并不是最左部分,因此不能使用该索引。在实际应用中,这种设计有助于我们合理创建索引
- 并按照最左前缀原则编写我们的查询,以提高查询效率。
创建索引时需要注意什么?
创建索引时需要注意的主要因素有:
- 选择性选择性指的是字段中不重复值与总行数的比值。
- 选择性越高,使用索引查询起来效率越高。
- 因此,通常我们喜欢在高度选择性的列上创建索引。
数据类型:
- 较小的数据类型普遍来说在索引上性能更好,因为它们占用的空间更小。
索引维护成本:
- 每当更改表中的数据(
INSERT、UPDATE、DELETE
)时,索引都需要被更新。
- 对于大量的写入操作,索引的维护成本可能会变得非常高。
覆盖索引:
- 如果一条查询语句的执行只需要访问索引,而不需要访问实际的行记录
- 那么这个查询就是一个覆盖索引查询,这样的查询执行效率最高。
什么是MySQL事务?
MySQL事务是一组数据库操作(例如插入、更新、删除等)
- 这些操作被视为一个逻辑单元,要么全部成功执行,要么全部回滚(撤销)。
通过使用事务,可以确保数据库操作的一致性和可靠性。
当多个操作需要作为一个逻辑单元执行时,可以将它们放在一个事务中,以保证数据的完整性。
- 事务可以通过使用
BEGIN
、COMMIT
和ROLLBACK
等SQL语句来控制。
事务的四大特性介绍一下?
事务具有以下特性,通常称为
ACID
特性:原子性(Atomicity):
- 事务中的操作要么全部执行成功,要么全部回滚,不会出现部分执行的情况。
- 如果任何一个操作失败,整个事务都会被回滚到初始状态。
一致性(Consistency):
- 事务在执行前后,数据库必须保持一致的状态。
- 这意味着事务的操作不会破坏数据库的完整性约束,如外键、唯一性约束等。
隔离性(Isolation):
- 事务的执行应该与其他并发事务隔离开来,每个事务都应该感知不到其他事务的存在。
- 隔离级别定义了事务之间的可见性和影响,包括读未提交、读已提交、可重复读和串行化。
持久性(Durability):
- 一旦事务提交成功,其结果应该永久保存在数据库中,即使在系统故障或重启后也不会丢失。
为什么MySQL要区分多种隔离级别?
在数据库系统中,事务是一个不可分割的工作单位
- 而隔离级别是为了在并发控制中解决数据一致性和并发性之间的问题。
MySQL定义了四个事务隔离级别:读未提交、读已提交、可重复读、串行化
- 它们分别解决了脏读、不可重复读和幻读这三类问题。
读未提交 (READ UNCOMMITTED):
- 最低的隔离级别,事务未提交时,其他事务能看到其改动,容易导致脏读。
读已提交 (READ COMMITTED):
- 不同的事务之间可以看到对方已提交的改动,但并不能看到未提交的改动
- 可以防止脏读,但可能导致不可重复读。
可重复读 (REPEATABLE READ):
- MySQL默认的隔离级别,在同一事务里的查询结果是一致的
- 解决了不可重复读问题,但可能出现幻读。
串行化 (SERIALIZABLE):
- 最高的隔离级别,所有的事务将串行执行,能防止所有并发问题,但性能低下。
为什么要区分这么多隔离级别呢?
- 其实是因为一致性和性能之间的平衡。
- 隔离级别越高,数据的一致性保证越好,但并发性能可能就会变差。
- 反之,隔离级别越低,并发性能越好,但可能会存在数据一致性问题。
- 所以,用户可以根据自身业务的需求,选择合适的隔离级别。
什么叫做脏读?
脏读(
Dirty Read
)是指一个事务在读取其他事务尚未提交的数据时发生的情况。
- 换句话说,脏读是指事务读取了其他事务尚未完成的、可能会被回滚的数据。
具体来说,当一个事务在读取数据的过程中,另一个事务对这些数据进行了修改,但尚未提交。
- 如果第一个事务读取了这些尚未提交的数据,并基于这些数据进行了操作,那么就发生了脏读。
脏读可能会导致数据的不一致性和错误的结果。
- 因为尚未提交的数据可能会被回滚,所以第一个事务基于这些数据所做的操作最终可能是无效的。
什么是幻读?
幻读(
Phantom Read
)是指在一个事务中,前后两次相同的查询操作返回的结果集不一致的情况。
- 换句话说,幻读是指在两次相同的查询操作之间,有另一个事务插入或删除了符合查询条件的数据
- 导致第一次和第二次查询的结果不一样。
具体来说,当一个事务在执行某个范围查询时,比如使用
SELECT ... WHERE
语句
- 第一次查询返回了一些满足条件的行,但在事务继续执行的过程中
- 另一个事务插入了一些新的符合查询条件的行
- 导致第二次相同的查询返回的结果集比第一次更多。
幻读与脏读的区别在于,脏读是读取了其他事务尚未提交的数据,而幻读是读取了其他事务已经提交的数据
- 但这些数据在当前事务的两次查询之间发生了变化。
如何解决幻读问题?
MySQL中解决幻读问题的方式是设置隔离级别为可重复读(
Repeatable Read
)或者串行化(Serializable
)。在可重复读隔离级别中,MySQL使用了多版本并发控制(MVCC)机制来防止幻读
- 同一事务内的多个查询看到的都是同一快照的数据,确保了数据的一致性。
串行化隔离级别则是通过对所有读取的行加锁来防止幻读发生,它提供最严格的隔离级别
- 在这种隔离级别下,所有的事务将顺序执行,因此也就不存在幻读这种问题。
- 但是这种级别会严重下降并发性能。
此外,如果你要对数据进行修改操作,并希望在操作期间防止新的记录插入
你还可以进一步使用
SELECT … FOR UPDATE
语句来对数据加锁。这样可以防止在当前事务提交之前,任何其他事务插入符合当前查询条件的新记录。
什么是不可重复读?
不可重复读是指在同一个事务中,读取相同的数据多次,但是得到的结果却不一致的现象。
- 这是因为在不可重复读的情况下,其他事务可能已经对数据进行了修改或者删除操作。
举个例子来说,假设有一个商品库存表,事务A在开始时读取某个商品的库存数量为10
- 在事务A进行其他操作的过程中,事务B对该商品进行了一次库存减少的操作,使得库存数量变为了9。
- 然后事务A再次读取该商品的库存时,得到的结果却是9,与之前的读取结果不一致
- 这就是不可重复读的情况。
什么是MVCC?
MVCC(Multi-Version Concurrency Control)
是一种并发控制机制
- 用于在数据库系统中处理并发读写操作的一致性问题。
在传统的并发控制机制中,比如锁机制,读操作会对数据加锁,写操作会对数据加排他锁
- 以防止并发操作导致的数据不一致性。
- 但是锁机制会带来死锁、性能下降等问题。
而MVCC机制则采用了更加灵活的方式来处理并发问题。
它基于时间戳的概念,为每个数据版本都分配了一个唯一的时间戳。
当一个事务开始时,它会读取当前的数据版本,并将该版本的时间戳作为自己的读取时间戳。
在事务执行期间,它只能看到在该时间戳之前已经提交的数据版本。
- 对于写操作,事务会创建一个新的数据版本,并将其时间戳设置为当前时间戳。
这样,不同事务之间的读写操作可以同时进行,不会相互阻塞,提高了并发性能。
- 同时,MVCC也保证了事务之间的隔离性,避免了不可重复读、幻读等问题。
MVCC在许多数据库系统中得到了广泛的应用
- 比如MySQL的
InnoDB
存储引擎就采用了MVCC机制来处理并发控制。
MySQL有哪些锁?
MySQL主要有以下三种锁:
表锁(Table Lock):
- 顾名思义,它锁定的是整个表。
- 这是MySQL中最基本的锁策略,它会锁定整个表
- 让其他所有的写操作(插入、删除、更新)和可能读取不同版本数据的读操作等待,直到锁被释放。
- 例如,当对一张表进行写操作时,需要对其加表锁
- 这期间其他任何人都无法对表进行修改,可以进行读取。
行锁(Row Lock):
- 行锁是MySQL中最细粒度的锁,它可以锁定一行数据。
- 行锁能够最大程度地支持并发处理(同时也带来了最大的锁开销)。
- 比如,当我们更新一条数据时,只有这条数据被锁住,不会影响到其他行的操作。
页锁(Page Lock):
- 页锁是介于表锁和行锁之间的锁策略,它锁定的是数据库的某一页,这个页中包含了很多行。
- 页锁的开销和死锁可能性介于表锁和行锁之间。
这三种锁各有优缺点。表锁开销小,加锁快,不会出现死锁,锁定粒度大,发生冲突的概率最高,并发度最低。
行锁开销大,加锁慢,会出现死锁,锁定粒度小,发生冲突的概率最低,并发度也最高。
页锁则介于两者之间。
MySQL行锁底层实现?
MySQL的行锁是通过索引来实现的。
也就是说,只有通过索引条件检索数据,MySQL才使用行级锁,否则,MySQL将使用表锁。
- 这也意味着如果在执行
UPDATE、DELETE
等操作时,如果没有使用索引
- 那么MySQL将使用表锁而不是行锁,这可能会导致大量的阻塞操作。
MySQL的行锁有两种模式:
共享锁(
Shared Locks
,简称S锁)和排他锁(Exclusive Locks
,简称X锁)。
- 共享锁(S锁):
- 允许一个事务去读一行,阻止其他事务对其进行修改。
- 排他锁(X锁):
- 允许获取锁的事务更新数据,阻止其他事务取得同一数据行的读锁和写锁。
当一个事务已经持有了某行数据的S锁,其他事务可以继续获取该行的S锁
- 但不能获取X锁,直到已经持有S锁的事务释放锁。
当一个事务已经持有了某行数据的X锁,其他事务不能再获取该行的任何锁,直到已经持有X锁的事务释放锁。
在InnoDB引擎中,行锁是通过给索引项上的索引记录加锁来实现的。
如果一个操作符合索引,则InnoDB只给符合条件的索引记录加锁
- 如果一个操作不符合索引,InnoDB则会对表中所有的记录加锁,此时的行锁就升级为表锁了。
数据库悲观锁和乐观锁介绍一下?
悲观锁和乐观锁是在并发控制中常用的两种锁机制
- 用来解决多个事务同时操作数据时可能出现的问题。
悲观锁(Pessimistic Locking)
- 是假设最坏的情况,每次去获取数据的时候都认为其他事务会修改数据,所以在整个数据处理过程中将数据锁定
- 其他事务无法进行修改,直到该事务完成。
- 在数据库中,悲观锁一般就是我们提到的行锁或表锁,如
SELECT…FOR UPDATE
就是典型的悲观锁操作。乐观锁(Optimistic Locking)
- 则是假设最好的情况,每次去获取数据的时候都认为其他事务不会修改数据,所以不会上锁
- 但是在更新时会判断在此期间有没有其他事务更新了这个数据。乐观锁适用于读多写少的应用场景
- 因为不用经常去做数据的互斥操作,可以提高并发效率。
- 乐观锁在数据库中一般是通过版本号机制实现的,每次读取数据时都会获取当前的版本号
- 在更新时比较版本号,如果版本号发生改变,则说明有其他事务已经修改了数据
- 那么就需要进行相应的处理,如重试或者回滚。
什么是 redo log?有什么用?
redo log
,也被称为重做日志
- 是MySQL数据库中InnoDB存储引擎的一个重要概念。
在数据库中,为了提高性能,数据在更新的时候并不是直接更新在磁盘上,而是先更新在内存中
- 然后通过后台的方式慢慢刷(
flush
)到磁盘。但是这种方式存在一个问题- 那就是如果数据库在数据还没有刷到磁盘的时候发生了崩溃,那么这部分数据就会丢失。
这时,就需要使用到
redo log
。当数据更新的时候,InnoDB引擎会先把记录写到
redo log
中,并更新内存
- 这个时候更新就算完成了。
- InnoDB引擎会在适当的时候,将这个操作记录更新到磁盘中。
- 并且,
redo log
是循环写的,当写到末尾时,又会从头开始写。这样做的好处是,即使数据库发生崩溃,只要
redo log
还在
- 就可以通过
redo log
把数据恢复到最新的状态。- 因此,
redo log
主要是用来保证事务的持久性(Durability
)。需要注意的是,
redo log
是InnoDB存储引擎特有的,其他存储引擎不一定有类似的机制。
什么是 undo log?有什么用?
undo log
,也称为回滚日志,是MySQL数据库中InnoDB存储引擎的一个重要概念。在数据库中,
undo log
主要有两个作用:提供了事务的回滚功能。
- 当一个事务执行过程中出现错误,或者在一定的情况下需要主动回滚一个事务时
- InnoDB可以通过
undo log
把数据恢复到事务开始之前的状态。为了实现多版本并发控制(MVCC)提供了一种机制。
- 在执行读操作时,为了能读取到一个一致性的快照
- 需要通过undo log来获取数据在某个时间点的版本。
undo log的存储形式是逻辑日志,记录的是数据被修改的逻辑情况
- 比如 某行数据的某列从A修改为B。
需要注意的是,
undo log
也是InnoDB存储引擎特有的,其他存储引擎不一定有类似的机制。
什么是bing log?有什么用?
bin log
,也称为二进制日志,是MySQL数据库中的一个重要概念。它记录了所有修改了数据或者可能修改数据的SQL语句
- 比如
INSERT、UPDATE、DELETE
等等,以二进制形式保存。
bin log
主要有以下两个作用:数据恢复:
- 如果数据库发生崩溃,可以通过重新执行
binlog
中记录的SQL语句来恢复数据。主从复制:
- 在MySQL的主从复制中,主服务器上的数据更新会写入到
bin log
中
- 然后从服务器通过读取并执行
binlog
中的SQL语句来实现和主服务器的数据同步。
bin log
和InnoDB存储引擎的redo log、undo log
不同
- 它不是InnoDB特有的,其他存储引擎也可以使用。
需要注意的是,
bin log
是以追加的方式写入的,所以在某些情况下
- 如果
bin log
的积累过多,可能会占用大量的磁盘空间,需要定期进行清理。
redo log 和 bing log有什么区别?
redo log
和bin log
都是MySQL数据库的日志系统的重要组成部分
- 它们都对数据库的恢复和复制起着重要作用,但是它们之间有一些主要的区别:
存储引擎:
redo log
是InnoDB存储引擎特有的日志- 而
bin log
是MySQL的服务器层实现的,所有的存储引擎都可以使用。日志内容:
redo log
是物理日志,记录的是在某个数据页上做了什么修改
- 比如 在某个数据页上的某个偏移量上写入了什么数据。
- 而
bin log
是逻辑日志,记录的是这个操作是什么,比如 给表T中的ID=2这一行的列N加1。写入时机:
redo log
在事务执行过程中持续写入,当事务提交时,必须确保redo log
已经写入磁盘。
- 而
bin log
默认情况下是在事务提交完成后写入。日志的用途:
redo log
主要用于保证事务的持久性,即在数据库发生异常重启后,通过redo log
恢复数据。- 而
bin log
主要用于实现MySQL的主从复制,从库会读取主库的bin log
来进行数据同步
- 同时,
bin log
也常常用于数据恢复。日志的格式:
redo log
是固定的格式,而bin log
有三种格式:statement、row和mixed
。
MySQL常见引擎有哪些?
MySQL的存储引擎是用来存储和管理数据的组件,不同的存储引擎提供了不同的存储机制、索引技巧、锁定水平等功能。
- MySQL最常见的引擎主要有以下几种:
InnoDB:
- 这是MySQL的默认存储引擎,支持事务处理和行级锁定,提供了提交、回滚、崩溃恢复能力
- 支持外键,可以进行外键和非空约束。
MyISAM:
- 这是MySQL的传统存储引擎,不支持事务和行级锁,只支持表级锁。
- MyISAM的优点是插入数据速度快,占用的磁盘空间相对较小。
- 但是,由于不支持事务,安全性不如InnoDB,一般用于只读或者小型应用。
MEMORY:
- 所有的数据都在内存中,数据的处理速度快,但是安全性不高,如果数据库重启,所有的数据都会消失。
- 一般用于存储临时数据。
Archive:
- 只支持INSERT和SELECT操作,适合存储和检索大量的历史数据。
BLACKHOLE:
- 黑洞引擎,它不存储数据,插入的数据会被丢弃,但是可以被用在复制的场景,如主从复制。
Federated:
- 联邦存储引擎,可以把一些远程的数据表映射为本地的一张表,使用这张表时实际上访问的是远程的数据。
每种存储引擎都有其适用的场景,需要根据实际需要选择合适的存储引擎。
InnoDB 和 MyISAM 有什么区别?
MyISAM和InnoDB是MySQL最常用的两种存储引擎,他们在很多方面都有不同,主要有以下几点:
事务支持:
- InnoDB支持事务,其设计目标就是处理大容量数据库系统。
- MyISAM不支持。
锁级别:
- InnoDB支持行级锁(即:当用户对一条记录进行操作时,只影响这条记录)
- MyISAM只支持表级锁(即:当对一条记录进行操作时,整张表被锁住,其他人无法对此表进行操作)。
数据完整性:
- InnoDB支持外键,可以进行外键和非空约束,利于保持数据的完整性。
- MyISAM不支持。
崩溃恢复:
- InnoDB可以通过日志进行恢复,对于数据安全性较高的环境,如银行、电子商务等场景会使用InnoDB。
- MyISAM则无法进行这样的恢复。
全文索引:
- MyISAM支持全文索引,但InnoDB在MySQL 5.6.4版本后,也支持全文索引。
数据缓存:
- InnoDB会将数据和索引都缓存在内存中,而MyISAM只将索引缓存到内存中。
在实际应用中,如果表需要频繁的大量插入、删除,更新操作且需要较高的事务安全性,InnoDB是一个很好的选择
- 如果表数据相对稳定,而偏重于查询,那么MyISAM可能会更有效率。
什么是分库分表?
分库分表是数据库设计中的一种常见策略,通常用于处理大数据量和高并发的场景。
这种策略的主要目的是为了提高数据库的性能和扩展性。
分库:
- 分库就是将一个数据库分解为多个较小的数据库。
- 每个小数据库都独立运行在一个服务器或服务器集群上,这样可以分散数据库的负载,提高数据库的性能和可用性。
- 分库可以是垂直分库,也可以是水平分库。
- 垂直分库是按业务模块将数据库拆分,每个数据库包含相关的表
- 水平分库则是将一份数据分散到多个数据库中。
分表:
- 分表就是将一个大表分解为多个较小的表。
- 每个小表都独立存储一部分数据,这样可以减少单个表中的数据量,提高查询和写入的速度。
- 分表也可以是垂直分表,也可以是水平分表。
- 垂直分表是将表中的列拆分到不同的表中,每个表包含部分列
- 水平分表则是将表中的行拆分到不同的表中,每个表包含部分行。
总的来说,分库分表是一种将数据分散到多个数据库和表中的策略
- 它可以有效地提高数据库的性能和扩展性,但同时也增加了数据库管理的复杂性。
在实际应用中,需要根据具体的数据量、并发量、业务需求等因素来决定是否需要进行分库分表
- 以及如何进行分库分表。
垂直分表和水平分表的区别?
垂直分表和水平分表都是数据库分表的策略,但它们的侧重点和应用场景有所不同:
垂直分表:
- 垂直分表是按照字段进行分表,将一张表的某些列拆分出来,形成新的表。
水平分表:
- 水平分表是按照记录进行分表,将一张表的数据记录按照某种规则(如id范围、哈希值等)拆分到多张表中。
总的来说,垂直分表通常用于解决表字段过多的问题,而水平分表通常用于解决单表数据量过大的问题。
- 在实际应用中,需要根据具体的业务需求和数据情况来选择合适的分表策略。
分库分表存在哪些问题
主要包括以下几个方面:
数据一致性:
- 分库分表后,数据将分布在多个数据库或表中,如何保证数据的一致性是一个挑战。
- 例如,如果一个事务需要操作多个数据库或表,那么就需要进行分布式事务处理,这会增加系统的复杂性。
跨库跨表查询:
- 分库分表后,原本在单一数据库或表中可以轻松处理的跨表查询变得困难,可能需要在应用层进行多次查询和数据合并。
数据迁移:
- 如果需要进行数据库或表的扩容,可能需要对数据进行迁移,这会带来一定的工作量和风险。
分库分表策略:
- 如何制定合理的分库分表策略也是一个问题,需要根据业务特性和数据访问模式进行考虑
- 否则可能会导致数据分布不均,无法达到预期的性能提升。
维护成本:
- 分库分表会增加系统的复杂性,对于开发和运维人员来说,需要更多的工作和学习成本
- 比如对分布式事务、分布式锁等技术的理解和使用。