1、什么是MySQL事务?
可以从事务的定义、ACID特性、使用场景、隔离级别等方面回答。
事务是由MySQL的引擎来实现的,我们常见的InnoDB引擎它是支持事务的(MyISAM引擎不支持)。
MySQL事务是指一组SQL操作,要么全部执行成功,要么全部执行失败,是保证数据一致性和完整性的重要手段。一个事务必须具备ACID四个特性,即原子性、一致性、隔离性和持久性(可分别说说它们的特点)。MySQL提供了四种隔离级别:读未提交、读已提交、可重复读和串行化。在使用MySQL事务时,需要注意事务的开启、提交和回滚操作,以及事务的嵌套和异常处理等问题。MySQL事务使用场景:转账操作、订单提交等。
补充:原子性、一致性、持久性说的都是mysql的可靠性方面的考量,隔离性说的则是在并发场景下,同时有读和写的情况如何做到数据隔离,到底数据要隔离到什么程度,则就有了隔离级别的概念。
2、ACID靠什么保证?
- 原子性(Atomicity):事务中的所有操作都要么全部执行成功,要么全部失败回滚,不会出现部分执行的情况。
- 一致性(Consistency):事务的执行不会破坏数据库的完整性和约束条件,事务执行前后数据库的状态必须保持一致。
- 隔离性(Isolation):事务的执行应该与其他事务隔离开来,一个事务的执行不应该影响其他事务的执行,事务应该独立于其他事务。
- 持久性(Durability):事务一旦提交,其结果就应该永久保存在数据库中,即使系统崩溃也不应该丢失事务的结果。
ACID特性的实现方式:
-
原子性:MySQL使用了两种日志来保证事务的原子性,即重做日志(redo log)和撤销日志(undo log)。重做日志记录了事务所做的修改,而撤销日志记录了事务所做的回滚操作。在执行事务时,MySQL会先将事务的修改记录在重做日志中,然后再执行实际的修改操作。如果事务执行失败,MySQL会根据重做日志和撤销日志来回滚事务。
-
一致性:MySQL使用事务的隔离级别和锁机制来保证一致性。(一致性是最基本的属性,其它的三个属性都为了保证一致性而存在)
-
隔离性:MySQL支持四种隔离级别,包括读未提交、读提交、可重复读和串行化。在实现隔离性时,MySQL使用了多种锁机制,包括共享锁、排他锁、意向锁等。不同的隔离级别使用不同的锁机制来实现。
-
持久性:MySQL使用了多种机制来保证持久性,包括缓冲区和写前日志。缓冲区用于提高事务的性能,写前日志用于保证事务提交后的修改能够被持久化到磁盘中。在写前日志中,MySQL会先将事务的修改记录到日志文件中,然后再将修改写入磁盘。如果系统在写入磁盘时出现故障,MySQL可以通过重做日志来恢复事务的修改。
综上,MySQL通过使用重做日志、撤销日志、约束检查、锁机制、写前日志等多种技术手段来实现事务的ACID特性。这些机制相互配合,保证了事务的正确性和可靠性。
3、MySQL事务的隔离级别有哪些?它们之间有什么区别?
MySQL事务的四种隔离级别:读未提交(Read Uncommitted)、读提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。
它们的区别主要在于一个事务可以读取或修改其他事务已提交或未提交的数据的程度不同。 下面是精简版回答:
- 读未提交:事务可以读到其他事务未提交的数据,数据最不安全,并发性最好。可能发生脏读、不可重复读和幻读。
- 读已提交:事务仅能读取到已经提交的数据,相对于读未提交来说较为安全,但仍然存在“不可重复读”和“幻读”的问题,但是不可能发生脏读。
- 可重复读(InnoDB默认隔离级别):一个事务多次读取同一行数据,读取的结果都是一致的,相对于读已提交来说更安全,但仍然存在“幻读”的问题,但是不可能发生脏读和不可重复读(未提交变更对其他事务是不可见的)。
- 串行化:所有操作都是串行执行的,可以避免“脏读”、“不可重复读”、“幻读”的出现,但是性能较差。(串行化,顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行)
隔离级别从低到高依次为读未提交、读提交、可重复读和串行化。隔离级别越高,数据的一致性越好,但是并发性能也越差。开发人员需要根据具体业务场景选择合适的隔离级别。
我们可以通过SELECT @@tx_isolation;命令查看当前默认隔离级别,MySQL8.0该命令改为SELECT @@transaction_isolation;
mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
4、并发事务带来了哪些问题?
MySQL 服务端是允许多个客户端连接的,这意味着 MySQL 会出现同时处理多个事务的情况。
那么在同时处理多个事务的时候,就可能出现数据库的一致性问题、更新丢失、脏读、不可重复读、幻读。
5、什么是脏读、不可重复读和幻读?如何避免这些问题?
-
脏读:指一个事务读取到了另一个事务未提交的数据。当另一个事务回滚或修改这些数据后,读取到该数据的事务可能得到一个不一致的结果。
- 解决方法:可以通过设置事务隔离级别来避免。通常情况下,使用Serializable级别可以避免脏读问题。
-
不可重复读:指一个事务执行过程中,多次读取同一行数据时,由于其他事务的修改或删除,前后两次读取的数据不一致的问题。不同于脏读,不可重复读读取到的数据是已经提交的被其他事务修改的数据,而非未提交的数据。这会导致程序对数据处理的不一致甚至错误,影响数据库的正确性和可靠性。通常使用事务隔离机制,如可重复读隔离级别等来解决这种问题。
- 解决方法:采用可重复读及串行化这几种隔离级别来解决这种问题,可重复读可以通过MVCC的机制来避免这种问题的发生。
-
幻读:指在一个事务中,同样的条件下,两次查询返回的记录数不一致,这是因为在两次查询的期间,另一个事务插入或删除了符合条件的记录,导致两次查询的结果不一致。 (幻读的重点在于新增或者删除)
- 解决方法:InnoDB 是采用 next-key + MVCC 去解决幻读问题的!
-
- 在 RR 的隔离级别下,Innodb 使用 MVCC 和 next-key locks 解决幻读
-
- MVCC 解决的是快照读的幻读
-
- next-key locks 解决的是当前读情况下的幻读
不可重复读和幻读区别:
不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次查询同一条查询语句(DQL)时,记录发现记录增多或减少了。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| Read Uncommitted | ✔ | ✔ | ✔ |
| Read Committed | ✘ | ✔ | ✔ |
| Repeatable Read | ✘ | ✘ | ✔ |
| Serializable | ✘ | ✘ | ✘ |
6、MySQL事务如何数据恢复?
一些常用的方法:
- 回滚事务:通过rollback语句可以撤销之前执行的一条或多条SQL语句,将数据恢复到事务开始前的状态。
- 使用备份进行恢复:可以使用MySQL自带的工具如mysqldump或第三方备份工具(如XtraBackup)创建备份文件。将备份文件导入到MySQL中即可完成数据恢复。
- 使用二进制日志恢复:MySQL的二进制日志可以记录所有数据库的修改操作。首先需要开启二进制日志记录功能,然后在需要进行数据恢复的时候,将所有的二进制日志文件导入到相应的MySQL实例中,即可完成数据恢复。
- 使用InnoDB引擎的恢复功能:InnoDB引擎提供了多种数据恢复工具,如使用日志文件进行恢复、使用redo log重做日志进行恢复等。
- 手动恢复:在某些情况下,如数据库损坏或遭受攻击,可能需要手动恢复数据。此时可以根据具体情况进行手动恢复,如利用备份文件从头开始恢复、使用数据恢复工具进行修复等。
需要注意的是,事务的恢复需要谨慎操作,避免误操作导致数据丢失或损坏。在进行数据恢复时,应备份原始数据,以防还原过程出现问题。
MySQL事务数据恢复是一种特定类型的数据恢复,主要是针对事务发生故障而需要恢复。而MySQL数据恢复则是指除事务数据恢复外的一般数据恢复。 MySQL事务数据恢复的机制是通过MySQL事务的ACID属性实现的。
7、什么是MVCC?
MVCC (Multi-Version Concurrency Control)指的是多版本并发控制,是指维护一条记录的多个版本,使得读写操作没有冲突。
它是MySQL中的提高性能的一种方式,配合Undo log 和版本链,替代锁,让不同事物的读-写、写-读操作可以并发的执行,从而提升系统的性能。
MVCC 在 MySQL InnoDB 中的实现主要是为了提高数据库并发性能。一般是在使用 读已提交 和 可重复读 隔离级别的事务中实现。
☃MVCC的实现原理
MVCC 的具体实现,依赖于数据库记录中的隐式字段、undo log 日志、readView。
在内部实现中,InnoDB 通过数据行的 DB_TRX_ID(最近更新的事务id) 和 Read View 来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR(回滚指针) 找到 undo log 版本链中的历史版本。这就是快照读
每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 Read View 之前已经提交的修改和该事务本身做的修改