Java-常见面试题收集(七)

十四 MySQL

1 MySQL 支持的存储引擎

  MySQL 支持多种存储引擎,常见的有2种,你可以通过 show engines 命令来查看 MySQL 支持的所有存储引擎。MySQL 当前默认的存储引擎是 InnoDB。并且,所有的存储引擎中只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务。

  InnoDB:版本:从 MySQL 5.5 开始,InnoDB 成为了默认的存储引擎。
  特点:支持事务安全(ACID兼容)表,提供行级锁定和外键约束。它适用于需要高并发写入和复杂事务处理的场景。InnoDB 还支持崩溃恢复和热备份等功能,确保数据的一致性和可靠性。
  性能:由于支持行级锁定,InnoDB 在处理并发写入时具有优势。此外,InnoDB 还支持哈希索引和全文索引(从 MySQL 5.6 开始)。

  MyISAM:版本:在 MySQL 5.5 之前,MyISAM 是默认的存储引擎。
  特点:MyISAM 不支持事务和外键约束,但它在某些方面具有良好的性能优势,特别是在读取操作方面。MyISAM 使用表级锁定,适用于读取操作远多于写入操作的场景。
  性能:MyISAM 的插入和查询速度通常较快,但由于其不支持事务,它在处理复杂事务时可能会遇到问题。此外,MyISAM 在服务器重启时可能会丢失未提交的数据。

2 介绍事务

  事务(Transaction)是数据库管理系统执行过程中的一个逻辑单位,它由一个或多个SQL语句组成,这些语句要么全部执行,要么全部不执行。事务是一个不可分割的工作单位,它确保数据库从一种一致性状态转变到另一种一致性状态。如果在执行事务的过程中发生错误,则可以利用事务管理(Transaction Management)机制将数据库恢复到事务执行前的状态。

  事务有四个基本特性,通常简称为ACID:

  原子性(Atomicity):事务是一个原子操作单元,其对数据的修改要么全部执行,要么全都不执行。这意味着事务是一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,不可能结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

  一致性(Consistency):事务必须使数据库从一个一致性状态变换到另一个一致性状态。一致性确保了事务将数据库从一个合法的状态转变到另一个合法的状态。即当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。

  隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务是不可见的。这意味着在事务完成之前,其他事务不能看到其修改。这确保了数据库并发执行的多个事务不会互相干扰。

  持久性(Durability):一旦事务提交,则其结果就是永久性的,即使系统崩溃也不会丢失。这意味着一旦事务提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其执行结果有任何影响。

  通过使用事务,可以确保数据的完整性和一致性,即使在多用户并发访问和修改数据的情况下也能保持数据的正确性。事务管理在数据库系统中是一个非常重要的概念,广泛应用于各种需要确保数据一致性和完整性的场景中。

3 并发事务带来的问题

  在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题。

  脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数
据是“脏数据”,依据“脏数据”所做的操作可能是不正确的

  丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务 1 读取某表中的数据 A=20,事务 2 也读取 A=20,事务 1 修改 A=A-1,事务 2 也修改 A=A-1,最终结果 A=19,事务 1 的修改被丢失。

  不可重复读(Unrepeatable read): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。

  幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。

4 不可重复读和幻读的区别

  不可重复读的重点是内容修改或者记录减少比如多次读取一条记录发现其中某些记录的值被修改;

  幻读的重点在于记录新增比如多次执行同一条查询语句(DQL)时,发现查到的记录增加了。

  幻读其实可以看作是不可重复读的一种特殊情况,单独把区分幻读的原因主要是解决幻读和不可重复读的方案不一样。

  举个例子:执行 delete 和 update 操作的时候,可以直接对记录加锁,保证事务安全。而执行 insert 操作的时候,由于记录锁(Record Lock)只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁(Gap Lock)。也就是说执行 insert 操作的时候需要依赖 Next-Key Lock(Record Lock+Gap Lock) 进行加锁来保证不出现幻读

5 SQL 标准定义的事务隔离级别

  SQL标准定义了四个事务隔离级别,这些隔离级别对事务处理的方式和并发控制有着不同的影响。

  读未提交(Read Uncommitted):在此隔离级别下,一个事务在还没提交时,它所做的变更就能被其他事务看到。这意味着未提交的数据修改对其他事务是可见的,可能导致脏读、不可重复读和幻读的问题。

  读已提交(Read Committed):这也是大多数程序库系统的默认隔离级别(但不是所有系统,例如MySQL的默认隔离级别是可重复读)。在此隔离级别下,一个事务提交之后,它做的变更才会被其他事务看到。这可以避免脏读,但不可重复读和幻读的问题仍然存在。

  可重复读(Repeatable Read):这是MySQL的默认隔离级别。在此隔离级别下,一个事务执行过程中看到的数据,总是跟该事务在启动时看到的数据一致。未提交的变更对其他事务是不可见的,这可以避免脏读和不可重复读的问题,但幻读仍可能发生。

  串行化(Serializable):这是最高级别的事务隔离,提供了最严格的事务隔离。在同一行记录的读写操作中,写操作会加写锁,读操作会加读锁。当读写锁发生冲突时,后访问的事务必须等待前一个事务执行完成才能继续执行。这种隔离级别能够避免所有并发问题,包括脏读、不可重复读和幻读,但性能可能会受到影响。

  选择哪个隔离级别取决于具体的应用场景和需求。在需要高并发性能的场景中,可能会选择较低的隔离级别以提高性能;而在对数据一致性要求极高的场景中,可能会选择较高的隔离级别以确保数据的正确性。需要注意的是,不同的数据库系统可能对这些隔离级别的实现和支持有所差异。

隔离级别脏读不可重复读幻读
READ-UNCOMMITTED
READ-COMMITTED×
REPEATABLE-READ××
SERIALIZABLE×××

6 MySQL 的隔离级别的实现

  SQL 的隔离级别基于锁和 MVCC 机制共同实现的。
  SERIALIZABLE 隔离级别,是通过锁来实现的。除了 SERIALIZABLE 隔离级别,其他的隔离级别都是基于 MVCC 实现。不过, SERIALIZABLE 之外的其他隔离级别可能也需要用到锁机制,就比如REPEATABLE-READ 在当前读情况下需要使用加锁读来保证不会出现幻读。

7 表级锁和行级锁的区别

  表级锁和行级锁是MySQL中两种主要的锁定机制,它们在锁定范围、并发能力、加锁开销以及资源消耗等方面存在显著的区别。

  锁定范围:
  表级锁:锁定的是整个表,即对该表的访问会受到更多的限制。当某个会话持有表级锁时,其他会话不能对该表进行写操作,直到锁被释放。这种锁定方式粒度较大,可能会影响到多个不相关的行。
  行级锁:锁定的只是表中的相关行,即只有持有锁的事务可以访问或修改被锁定的行,其他事务仍然可以操作该表的其他行。这种锁定方式粒度较细,能够更精确地控制对数据的访问。

  并发能力:
  表级锁:由于锁定整个表,所以其并发度相对较低,尤其在多用户并发访问和修改数据的场景下,可能会导致较高的锁冲突概率。
  行级锁:由于只锁定需要访问或修改的行,其并发度较高,能够支持更多的并发操作,减少锁冲突。

  加锁开销:
  表级锁:实现简单,资源消耗较少,加锁快。由于其锁定范围大,所以加锁的开销相对较小。
  行级锁:加锁粒度更细,需要维护更多的锁信息,因此加锁的开销相对较大,加锁速度也可能较慢。

  死锁风险:
  表级锁:由于其锁定范围大,通常不会出现死锁现象。
  行级锁:由于多个事务可能同时尝试锁定不同的行,因此存在死锁的风险。死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。

  支持的存储引擎:
  表级锁:MyISAM和InnoDB等存储引擎都支持表级锁。
  行级锁:主要是InnoDB存储引擎支持行级锁,而MyISAM只支持表级锁。

  表级锁和行级锁各有其优缺点,适用于不同的场景和需求。在选择使用哪种锁时,需要根据具体的应用场景、数据访问模式以及性能要求来权衡。

10 MySQL 可以存储文件(比如图片)吗

  MySQL 数据库本身不直接存储文件,如图片。但你可以通过几种方法在 MySQL 中处理文件数据:

  存储文件路径:
  你可以在 MySQL 表中存储文件的路径(例如,文件在服务器上的位置),然后在应用程序中根据这些路径来访问文件。这是最常见的方法,因为它将数据库的大小保持在可管理的范围内,同时允许你轻松地访问和管理文件。

  将文件内容转换为 BLOB:
  你可以将文件内容读取为二进制数据,然后将这些数据存储在 MySQL 的 BLOB(Binary Large Object)字段中。BLOB 字段可以存储大量的二进制数据。但是,这种方法有几个缺点:数据库大小会迅速增长,可能导致性能问题。备份和迁移包含大量 BLOB 数据的数据库可能会非常耗时和占用大量空间。=通过数据库直接管理文件内容可能不是最佳实践,因为数据库的主要目的是存储结构化数据。

  使用文件系统与数据库的结合:
  另一种方法是使用文件系统来存储文件,但在数据库中存储有关这些文件的元数据(如文件名、大小、创建日期等)。这样,你可以通过查询数据库来检索文件的元数据,并使用这些信息来定位和操作文件系统中的实际文件。

  大多数应用程序会选择第一种或第三种方法,因为这两种方法都提供了更好的可管理性和性能。如果选择将文件内容存储在数据库中,需要确保数据库服务器有足够的磁盘空间,并考虑备份和迁移的潜在挑战。

  若只是想存储图片,并且这些图片对应用程序很重要,那么将图片作为文件存储在服务器上,并在数据库中存储其路径或引用可能是最佳选择。这样可以保持数据库的整洁和高效,同时允许你轻松地访问和管理图片文件。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

泰勒疯狂展开

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

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

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

打赏作者

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

抵扣说明:

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

余额充值