MySQL数据库的一些常见问题

7 篇文章 0 订阅
4 篇文章 0 订阅

博主介绍:

我是了 凡 微信公众号【了凡银河系】期待你的关注。未来大家一起加油啊~


前言

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站: https://www.cbedai.net/lf

下面记录一些关于MySQL一些常见的问题


1. 数据库三大范式

  • 第一范式(1NF):数据库表中的所有列都是不可分割的基本数据项,即数据库表的每一列都是原子性的,不可再分解。(确保每列原子性,不可拆分)
  • 第二范式(2NF):在满足第一范式的基础上,非主键列必须完全依赖于主键,而不能只依赖于主键的一部分。(确保表种的每列都和主键相关)
  • 第三范式(3NF):在满足第二范式的基础上,非主键列之间不能存在传递依赖关系,即不能存在非主键列对其他非主键列的依赖。(确保每列都和主键列直接相关,而不是间接相关)

总结:这三个范式的目的是为了消除数据冗余、提高数据的完整性和一致性,保证数据的正确性和稳定性。

2. MySQL存储引擎Mylsam和InnoDB有哪些区别

  1. 事务支持:InnoDB支持事务,而MyISAM不支持事务。
  2. 锁级别:MyISAM在执行SELECT语句时,会对需要读取的数据表进行整表锁定,而InnoDB支持行级锁和表级锁。
  3. ACID属性:InnoDB是一个ACID兼容的存储引擎,它支持原子性、一致性、隔离性和持久性,而MyISAM则只支持持久性。
  4. 并发性:由于InnoDB支持行级锁,因此并发性能更好,同时也避免了表级锁带来的并发性问题。
  5. 外键支持:InnoDB支持外键,而MyISAM不支持。
  6. 数据缓存:InnoDB支持数据和索引的缓存,而MyISAM只支持索引的缓存。
  7. 适用场景:MyISAM适合于读取密集型的应用,例如数据仓库,而InnoDB适合于事务处理的应用,例如电子商务和银行系统。

总结:MyISAM和InnoDB各有优缺点,在实际应用中需要根据具体需求来选择使用哪种存储引擎

3. 什么是索引?都有哪些类型?有什么优点和缺点?

索引是一种用于提高数据库查询性能的数据结构。它类似于书中的目录,能够加速查找数据的速度,使得数据库查询更加高效。

索引的类型有很多种,主要包括以下几种:

  1. B-Tree索引:是最常用的一种索引类型,它是一种基于B-Tree数据结构的索引,用于快速查找具有某些值的行。B-Tree索引支持精确查找和范围查找,并且在查询较小的数据集时效果最佳。
  2. 哈希索引:是一种基于哈希表的索引,用于快速查找具有某些值的行。哈希索引仅支持精确查找,不能进行范围查找,但是在查询大数据集时,哈希索引比B-Tree索引更快。
  3. 全文索引:是一种用于在文本数据中查找特定单词或短语的索引,支持模糊查询和关键词查询。
  4. 空间索引:是一种用于查找具有特定地理位置的行的索引,支持地理位置查询和空间关系查询。

索引的优点包括:

  1. 提高查询性能:索引可以加速数据的查找和读取,使得查询更加高效。
  2. 减少数据读取量:索引可以避免全表扫描,减少数据的读取量,降低数据库的负载。
  3. 优化数据库结构:索引可以优化数据库表的结构,提高数据库的整体性能。

索引的缺点包括:

  1. 增加存储空间:索引需要占用存储空间,如果索引过多或过长,会占用大量的存储空间。
  2. 降低更新性能:对于经常进行插入、删除和更新操作的表,索引的维护会降低更新操作的性能。
  3. 可能导致查询性能下降:如果索引选择不当或者过多,会导致查询性能下降,甚至出现死锁等问题。因此,在创建索引时需要根据实际情况进行优化和选择。

4. B树和B+树的区别,聚簇索引和非聚簇索引的区别。什么是回表,怎么减少回表?

B树和B+树都是多叉树的一种,它们都可以用于实现数据库中的索引。B树的节点中既包含了索引键,也包含了指向数据的指针;而B+树的节点只包含索引键,数据则全部存放在叶子节点中。具体区别如下:

  1. B树中的每个节点都可以存放数据,而B+树的数据只存储在叶子节点中,而非中间节点。
  2. B+树中叶子节点之间有一个链表相连,因此可以很方便地进行范围查找和遍历。
  3. B+树相较于B树更加适合在磁盘等外存储介质上使用,因为B+树的内部节点存放的只是关键字,而不存储数据,可以减少I/O操作。

聚簇索引和非聚簇索引的区别:
聚簇索引是将数据存储与索引放在一起的索引方式,也就是说,聚簇索引的叶子节点就是数据页,数据页的顺序与索引页的顺序相同。非聚簇索引则是将数据和索引分别存储在不同的文件中。

区别如下:

  1. 聚簇索引在查询时可以直接找到数据行,速度较快,而非聚簇索引需要进行两次查找,先查找索引,再通过索引找到数据行,速度相对较慢。
  2. 聚簇索引只能有一个,因为数据与索引存储在一起,而非聚簇索引可以有多个。
  3. 聚簇索引只能建立在主键或唯一约束上,而非聚簇索引可以建立在任何列上

回表和如何减少回表:
在数据库查询时,如果需要查询的列不在索引中,或者需要查询的列在非聚簇索引中,但是需要通过非聚簇索引再次查找数据行,则称为回表。回表会增加额外的I/O操作,降低查询效率。

减少回表的方法如下:

  1. 尽可能地使用聚簇索引:聚簇索引可以减少回表的次数,提高查询效率。
    考虑使用覆盖索引:覆盖索引是指包含查询所需的所有数据的索引,因此查询时不需要回表。
  2. 尽可能地减少查询的列:只查询需要的列,不查询不需要的列,可以减少回表的次数。
  3. 优化SQL语句:编写高效的SQL语句,避免使用

5. 为什么会有索引失效的情况,索引调优有哪些方法?

索引失效通常是由于查询语句中的条件与索引不匹配而导致的。以下是一些常见的导致索引失效的情况:

  1. 不使用索引列:如果查询语句没有使用索引列,那么索引就无法发挥作用,查询将会全表扫描,效率低下。
  2. 在索引列上使用函数:如果查询语句在索引列上使用了函数,如使用了LOWER()函数将查询条件转换为小写,那么索引就无法被使用,查询将会全表扫描。
  3. 对索引列进行运算:如果查询语句对索引列进行了运算,如使用了+运算符将两个列相加作为查询条件,那么索引也无法被使用。
  4. 条件使用OR:如果查询语句中的条件使用了OR运算符连接多个条件,而这些条件只有部分可以使用索引,那么索引也无法被使用。

为了避免索引失效,可以考虑以下索引调优的方法:

  1. 确保查询语句使用索引列:查询语句应该使用索引列作为条件,这样索引才能被使用。
  2. 避免在索引列上使用函数或运算符:在查询语句中避免在索引列上使用函数或运算符,如果必须使用函数或运算符,可以考虑在查询之前对数据进行预处理,将结果存储到新的列中,然后使用这些新的列进行查询。
  3. 考虑使用复合索引:如果查询语句中有多个条件,可以考虑使用复合索引,将多个条件都包含在一个索引中。
  4. 使用索引覆盖查询:如果查询语句只需要返回索引列的值,可以使用索引覆盖查询,这样可以避免对表进行全表扫描。
  5. 使用合适的数据类型:在创建表时,应该使用合适的数据类型,这样可以提高索引效率,减少索引失效的概率。

总结:索引调优是一个复杂的过程,需要根据具体情况进行优化,以提高数据库的性能和效率。

6. MySQL中的锁有哪些?什么是next-key lock?

MySQL中的锁主要分为共享锁和排他锁两种。

  1. 共享锁(Shared Lock):共享锁又称为读锁,多个事务可以同时持有共享锁,并发读取同一份数据,不会互相影响,但是不能进行写操作。当一个事务持有共享锁时,其他事务只能获取共享锁,而不能获取排他锁。
  2. 排他锁(Exclusive Lock):排他锁又称为写锁,只能被一个事务持有,当一个事务持有排他锁时,其他事务无法获取共享锁或排他锁,只能等待该事务释放锁。排他锁既可以进行读操作,也可以进行写操作。

在MySQL中,使用next-key lock来实现范围查询时的加锁机制,即行锁和间隙锁的组合,也称为Next-Key锁。它是在InnoDB存储引擎中实现的,用于避免幻读问题。

当执行范围查询时,InnoDB会在满足条件的记录上加上行锁,同时在记录之间的间隙上加上间隙锁,这样可以避免其他事务插入符合条件的记录。这种锁的组合称为Next-Key锁。

举个例子:假设有一个表,包含3条记录:A、B、C。执行以下查询:

SELECT * FROM table WHERE id > 1 AND id < 4;

InnoDB会在记录B上加上行锁,并在记录A和记录C之间的间隙上加上间隙锁,这样其他事务无法插入id为2或3的记录。

需要注意的是,Next-Key锁只在repeatable read和read committed隔离级别下使用,在read uncommitted和SERIALIZABLE隔离级别下,使用的是间隙锁或行锁,而不是Next-Key锁。

7. 乐观锁与悲观锁

乐观锁和悲观锁是两种不同的并发控制机制,主要用于多个用户并发访问共享资源时保证数据的一致性。

悲观锁:
悲观锁是一种较为保守的并发控制方式。它认为并发访问时一定会出现冲突,因此在访问共享资源时先加锁,确保自己独占资源,防止其他并发访问的线程对该资源进行修改。悲观锁主要使用数据库中的行级锁或表级锁实现。悲观锁的缺点是会影响系统的并发性能,尤其是在高并发的情况下。

乐观锁:
乐观锁相对于悲观锁来说,它是一种乐观的并发控制方式。它认为并发访问时不会出现冲突,因此在访问共享资源时并不加锁,而是通过版本号等机制判断数据是否被修改。如果没有被修改,则允许操作;如果已经被修改,则不允许操作,需要进行相应的处理。乐观锁主要使用CAS(Compare And Swap)等算法实现。乐观锁的优点是可以提高系统的并发性能,但是在并发更新高的情况下容易出现ABA问题。

ABA问题:
ABA问题指的是在使用乐观锁进行并发控制时,由于共享资源被修改多次而导致的数据不一致问题。具体来说,如果有两个线程T1和T2同时读取一个共享变量V,T1先执行了一个操作将V的值由A变成了B,然后又将V的值由B变成了A;此时T2也开始执行,并且在T1的操作完成之后将V的值由A变成了C,然后又将V的值由C变成了A。此时,T1再次读取V的值时,仍然是A,虽然V的值没有被其他线程修改过,但是T1并不知道V的值已经被其他线程修改过,因此可能会误认为V的值没有被修改过,从而出现数据不一致的问题。

为了解决ABA问题,可以采用如下两种方式:

  1. 使用带有版本号的原子变量,每次更新时都将版本号加1。这样,在判断时不仅要判断值是否相等,还要判断版本号是否相等。
  2. 使用ABA问题的预防方案,例如使用读写锁或者采用悲观锁。在采用悲观锁的情况下,每次读取共享资源时都需要加锁,这样可以保证其他线程不能修改共享资源,从而避免了ABA问题的出现。

总结:乐观锁和悲观锁都是为了保证并发访问共享资源的数据一致性,但是它们的实现方式和适用场景不同。一般来说,在并发更新较少的情况下,可以采用乐观锁,可以提高系统的并发性能;而在并发更新较多的情况下,为了保证数据的一致性,可以采用悲观锁。

8. MySQL的事务隔离级别有哪些?MVCC是什么?

MySQL的事务隔离级别有以下4种:

  1. 读未提交(Read Uncommitted):允许一个事务读取另一个事务未提交的数据。这种隔离级别存在脏读、不可重复读和幻读的问题。
  2. 读已提交(Read Committed):要求一个事务只能读取另一个事务已经提交的数据。这种隔离级别解决了脏读的问题,但是仍然存在不可重复读和幻读的问题。
  3. 可重复读(Repeatable Read):保证在同一个事务中多次读取同一数据时,读取到的数据是一致的。这种隔离级别解决了不可重复读的问题,但是仍然存在幻读的问题。
  4. 串行化(Serializable):最高的隔离级别,强制事务串行执行,避免了幻读的问题,但是会影响并发性能。

MVCC是MySQL中实现多版本并发控制的一种机制,它是在可重复读隔离级别下实现的。MVCC将每一行数据看作一个版本,每个版本都有一个版本号和时间戳。读取操作只能读取时间戳小于等于当前事务时间戳的版本,写入操作会创建一个新的版本,并更新时间戳和版本号。这样可以实现多个事务同时对同一数据进行读操作,而不会相互影响,从而提高了并发性能。同时,MVCC还可以保证在可重复读隔离级别下不会出现幻读的问题。

9. 脏读,幻读,不可重复读是什么?是怎么解决的。

脏读(Dirty Read)指的是一个事务读取到了另一个事务未提交的数据,如果另一个事务回滚,则读取到的数据是无效的。脏读问题可以通过设置事务隔离级别为“读已提交”(Read Committed)来解决。

幻读(Phantom Read)指的是一个事务读取到了另一个事务在同一个范围内插入的数据,导致第一个事务后续查询的结果集不一致。幻读问题可以通过设置事务隔离级别为“可重复读”(Repeatable Read)或“串行化”(Serializable)来解决。

不可重复读(Non-repeatable Read)指的是一个事务多次读取同一数据,在事务执行过程中另一个事务对数据进行了修改,导致第一个事务多次读取同一数据时读取到的数据不一致。不可重复读问题可以通过设置事务隔离级别为“可重复读”(Repeatable Read)或“串行化”(Serializable)来解决。

解决以上问题的方法如下:

  1. 脏读问题可以通过将事务隔离级别设置为“读已提交”(Read Committed)来避免。
  2. 不可重复读问题可以通过将事务隔离级别设置为“可重复读”(Repeatable Read)或“串行化”(Serializable)来避免。
  3. 幻读问题可以通过将事务隔离级别设置为“可重复读”(Repeatable Read)或“串行化”(Serializable),或者使用行级锁或表级锁来解决。

10. 读已提交、可重复读、串行化分别是如何实现的?

它们分别通过不同的机制来实现数据的并发访问:

  1. 读已提交(Read Committed):该隔离级别要求一个事务只能读取另一个事务已经提交的数据。它通过在读取数据时加锁,保证读取到的数据是当前已提交的版本,而不会读取到未提交的脏数据。在该隔离级别下,其他事务可以修改数据,因此可能会出现不可重复读和幻读问题。
  2. 可重复读(Repeatable Read):该隔离级别保证在同一个事务中多次读取同一数据时,读取到的数据是一致的。它通过在事务启动时记录当前时间戳,然后在读取数据时只读取时间戳小于等于当前时间戳的版本。在该隔离级别下,其他事务可以插入新数据,但不能修改已有数据,因此不会出现不可重复读问题,但仍可能出现幻读问题。
  3. 串行化(Serializable):该隔离级别是最严格的隔离级别,它强制事务串行执行,避免了所有并发问题,但会影响性能。它通过在读取数据时对所有访问的数据加锁,防止其他事务对数据进行修改或插入,从而保证了数据的一致性和唯一性。

需要注意的是,在可重复读隔离级别下,可能仍然存在幻读的问题,因为InnoDB只对已有的数据行生成多个版本,而对于新插入的数据行则没有生成多个版本,因此,如果在事务中多次执行同一个查询,可能会看到不同的结果集。如果需要完全避免幻读问题,则需要使用串行化隔离级别。

11. MySQL删除数据时的一些注意事项。

在MySQL中,删除数据是一个常见的操作,但是需要注意以下一些事项:

  1. 使用事务:在进行数据删除操作时,建议使用事务来保证数据的一致性和完整性。如果删除一条记录时出现问题,事务可以回滚到删除之前的状态,避免数据丢失或不一致的情况发生。
  2. 慎用DELETE语句:DELETE语句会直接删除表中的数据,因此需要慎重使用。如果误删了数据,就无法恢复了。在删除数据之前,可以使用SELECT语句先查看一下将要删除的数据是否正确。
  3. 使用带WHERE子句的DELETE语句:如果不带WHERE子句执行DELETE语句,将会删除表中的所有数据,这是一种非常危险的操作。因此,执行DELETE语句时必须要带上WHERE子句,确保只删除符合条件的数据。
  4. 禁用TRUNCATE语句:TRUNCATE语句会删除整张表的数据,而且没有回滚操作,因此需要慎重使用。如果需要清空表中的数据,建议使用DELETE语句。
  5. 禁止在应用程序中使用DELETE FROM语句:在应用程序中使用DELETE FROM语句会导致大量的I/O操作和锁竞争,从而影响系统的性能。因此,建议使用
  6. TRUNCATE或者DROP TABLE来清空表中的数据。
    使用LIMIT子句:在执行DELETE语句时,建议使用LIMIT子句来限制删除的数据条数。如果不使用LIMIT子句,可能会导致删除整个表的数据。
  7. 优化DELETE语句:在执行DELETE语句时,可以使用索引来优化查询速度,避免全表扫描。如果删除的数据很多,可以考虑分批删除,每次删除一部分数据,避免锁表和I/O问题。

12. MySQL使用时的一些经验和优化

推荐文章:https://mp.weixin.qq.com/s/exPgSB0MNUnu0wMkThET1w

为了可以让大家能够系统的学习,推荐一些学习资源,需要的发送序号领取下载:

  • 000001:高性能MySQL
  • 000002:MySQL必知必会

创作不易,点个赞吧!
如果需要后续再看点个收藏!
如果对我的文章有兴趣给个关注!
如果有问题,可以关注公众号【了凡银河系】点击联系我私聊。


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

了 凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值