一、MySQL事务有哪些特性?
- 原子性(Atomicity):事务中的所有操作要么全部执行成功,要么全部失败回滚,不能只执行一部分操作。
- 一致性(Consistency):事务执行前后,数据库的完整性性约束没有被破坏,数据总是从一个一致性状态转移到另一个一致性状态。
举例说明:a向b转账,在这个过程中,不管转账成不成功,a跟b的总金额都是不会变的。
- 隔离性(Isolation):事务之间是相互隔离的,每个事务对其他事务的操作是透明的,一个事务的中间结果对其他事务是不可见的。隔离性可以防止并发执行的事务之间产生脏读、不可重复读、幻读等问题。
- 持久性(Durability):事务完成之后,对数据库的修改将永久保存在数据库中,即使系统故障也不会丢失。
事务四大特性是为了保证数据库的数据一致性和可靠性的,使得数据库在并发访问和故障恢复等复杂环境下,仍能保持数据的完整性。
二、MySQL是如何保证事务的四大特性?
谈MySQL事务,基本是从默认的引擎InnoDB去举例说明:
- 原子性是通过 undo log(回滚日志)来保证的。InnoDB使用回滚日志(undo log)来记录事务的操作,包括事务开始、修改数据和事务提交等。如果事务执行失败或回滚,InnoDB可以使用日志来撤销已经执行的操作,确保事务的原子性。
- 一致性是通过 redo log(重做日志)来保证的。在事务提交之前,InnoDB会将事务的修改操作先写入事务重做日志(redo log),然后再将数据写入磁盘。即使在系统崩溃或断电的情况下,InnoDB可以通过重放事务日志来恢复数据,确保事务的持久性。
补充:mysql对于事务的修改操作(增删改),并不是来一条执行一条的,而是先写入 redo log(重做日志)里面,批量去处理修改操作。redo log(重做日志)又是如何保证断电的时候不丢失呢?因为它不只是会在内存里去存,还会定期的做持久化操作,存储进磁盘里面。
- 隔离性是通过MVCC(多版本并发控制)和锁机制来保证的。
- 一致性是通过各种约束,如主键、外键、唯一约束等,加上事务的持久性、原子性和隔离性来保证的。
三、事务有哪些隔离级别?
1. 读未提交(Read Uncommitted)
特点:最低的隔离级别,当前事务在修改数据,即使未提交,也可以被其它事务读取的。
优点:并发性能最好,读取到的数据是最新的。
缺点:存在脏读(Dirty Read)问题,即使读取到未提交的数据,可能导致数据不一致性。
2.读已提交(Read Committed)
特点:保证事务读取到的数据都是已经提交的,其它事务提交的数据对该事务可见。
优点:避免了脏读的问题。
缺点:存在不可重复读(Non-Repeatable Read)问题,即同一个事务中,不同时间读取到的数据可能不一样。
3.可重复读(Repeatable Read)
特点:保证同一事务中,多次读取同一条记录时,读取到的数据都是一致的。是MySQL默认的事务隔离级别。
优点:避免了不可重复读的问题。
缺点:存在幻读(Phantom Read)问题,即在一个事务中,进行同一个范围查询的记录,但第二次查询却发现了新的记录。
4.串行化(Serializable)
特点:最高的隔离级别,将所有的事务串行执行,保证了数据的完全隔离。(也就是让事务排队,一个一个执行)
优点:避免了幻读问题。
缺点:并发性能最差,可能导致大量的锁等待和死锁。
补充说明:
脏读:读到了另一个事务中间状态的数据,但是那个事务不执行了,事务回滚了,最终你看到的数据没有落盘,你看到的数据是临时数据。
不可重复读:当前事务执行 select * from table where id=’5’获取到的user是王五,过一段时间再执行一次这个查询,查到的user变成小五了,在中间的时间里有其它事务修改了user,把王五改成了小五。
幻读:在一个事务中,执行两次同一个的范围查询,第二次查询却发现了新的数据。多出来的数据就叫幻象行。
四、什么是MVCC(多版本并发控制)?
MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种并发控制机制,用于在数据库系统中处理并发读写操作时保持数据的一致性和隔离性(主要用来解决幻读问题的)。
MVCC通过在每个数据行上保存多个版本的数据来实现并发读取和写入的一致性。
MVCC的核心思想是将每个事务的读操作与写操作解耦,通过保存数据的历史版本来实现并发控制。每个事务在开始时都会创建一个读视图(Read View),用于确定在事务开始时可见的数据版本。读视图包含一个事务开始时的系统版本号,用于数据行的版本号进行比较,以确定数据行时否对事务可见。
在MVC中,当一个事务执行写操作时,会生成一个新的数据版本,并将旧版本的数据保存在回滚日志(undo log)中。这样,其它事务在读取数据的时候,仍然可以访问到旧版本的数据,从而避免了幻读问题。
MVCC的工作流程如下:
读操作:当一个事务执行SELECT语句,会根据读视图的系统版本号和数据行的版本号进行比较,只读取在事务开始之前已经提交的数据行。这样,即使其它事务正在并发地插入和删除数据,事务仍然可以读取到一致的数据。
写操作:当一个事务执行INSERT、UPDATE或DELETE语句时,会生成新的数据版本,并将旧版本的数据保存在回滚日志中。这样,其它事务在读取数据时仍然可以访问到旧版本的数据,从而避免幻读问题。