开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 30 天,点击查看活动详情
ACID 特性
- 事务:一组数据库操作,要么全部成功,要么全部失败(回滚)。
ACID是数据库事务的四个基本特性的缩写,包括原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
- 原子性(Atomicity):事务是一个不可分割的最小工作单位,整个事务中的操作要么全部提交成功,要么全部回滚失败,事务的执行结果是完全成功或完全失败的,不会存在部分执行成功的情况。
- 一致性(Consistency):事务执行前后数据库必须处于一致的状态,事务执行的结果必须满足数据库的完整性约束和业务逻辑约束。如果一个事务执行成功,那么数据库的状态应该从一个一致的状态转变为另一个一致的状态。
- 隔离性(Isolation):事务的执行必须与其他事务的执行相互隔离,每个事务执行时,都应该像其他事务不存在一样,即并发执行的多个事务互不干扰。事务的隔离级别包括读未提交、读已提交、可重复读和串行化。
- 持久性(Durability):一旦事务提交成功,它所做的任何更改都将永久保存在数据库中,即使在系统故障或崩溃时也不会丢失。持久性通常通过将事务操作的结果写入磁盘等外部存储设备来实现。
ACID是保证数据库事务的一致性和完整性的关键特性,它确保事务在数据库中的正确性和可靠性。在数据库系统的应用中,ACID是非常重要的,因为它们确保了数据的正确性,可靠性和可重复性,同时也避免了数据丢失和冲突的问题。
隔离性问题
隔离性问题是在数据库中多个事务并发执行时可能出现的问题,包括脏读、不可重复读和幻读。
- 脏读(Dirty Read):当一个事务读取了另一个事务未提交的数据时,就会发生脏读。例如,事务A读取了事务B修改但未提交的数据,如果事务B回滚了操作,那么事务A读取到的数据就是无效的,这种情况可能会导致数据的不一致性和错误的计算结果。
- 不可重复读(Non-repeatable Read):当一个事务多次读取同一数据时,如果其他事务在这个时间段内对该数据进行了修改或删除操作,就会出现不可重复读问题。例如,事务A在读取数据时,事务B修改或删除了该数据,当事务A再次读取该数据时,得到的结果可能已经发生了改变,这种情况可能会导致数据的不一致性和错误的计算结果。
- 幻读(Phantom Read):当一个事务多次读取同一范围的数据时,如果其他事务在这个时间段内对该范围的数据进行了新增或删除操作,就会出现幻读问题。例如,事务A在读取一个范围内的数据时,事务B新增了一条符合条件的数据,当事务A再次读取该范围的数据时,就会发现有一条新数据,这种情况可能会导致数据的不一致性和错误的计算结果。
以上这些问题都是由于多个事务并发执行时,读写操作之间的相互影响所引起的,需要使用适当的隔离级别来解决这些问题。通常来说,读已提交和可重复读是应用最广泛的两个隔离级别,可以满足大部分应用的需求。
锁
通过加锁可以保证ACID特性,MySQL中常用的锁类型包括以下几种:
- 共享锁(Shared Locks):也称为读锁,多个事务可以同时持有共享锁,用于保护读操作不被其他事务修改,不会阻塞其他事务的共享锁和排它锁,但会阻塞其他事务的排它锁。
- 排它锁(Exclusive Locks):也称为写锁,一个事务持有排它锁时,其他事务无法获得共享锁或排它锁,用于保护写操作不被其他事务干扰,会阻塞其他事务的共享锁和排它锁。
- 行锁(Row Locks):锁定表中的单独一行或多行,用于保护单个行不被其他事务修改。
- 间隙锁(Gap Locks):锁定范围而不是行,保护索引范围内的空间,防止其他事务插入新行。
- 临键锁(Next-Key Locks):是行锁和间隙锁的组合,保护索引范围内的行和间隙,防止其他事务在间隙中插入新行。
- 表锁(Table Locks):锁定整个表,用于保护整个表不被其他事务修改。
在 MySQL 中,不同的存储引擎支持的锁类型可能有所不同,而且使用不同的锁类型会对数据库的性能产生不同的影响。开发人员需要根据具体情况选择合适的锁类型来保证数据的正确性和性能的高效。
隔离性级别
数据库隔离级别是指数据库中多个事务之间相互隔离的程度。不同的隔离性程度,解决了不同的隔离性问题,常见的隔离级别包括以下四种:
- 读未提交(Read Uncommitted):在这个级别下,一个事务可以读取另一个事务未提交的数据,这种隔离级别最容易产生脏读、不可重复读和幻读的问题。
- 读已提交(Read Committed):在这个级别下,一个事务只能读取另一个事务已经提交的数据,解决了脏读的问题,但可能会出现不可重复读和幻读的问题。
- 可重复读(Repeatable Read):在这个级别下,一个事务在执行期间读取的所有数据都是一个静态快照,其他事务对该数据的修改只能在该事务结束后才能执行,解决了不可重复读的问题,但可能会出现幻读的问题。
- 序列化(Serializable):在这个级别下,所有事务依次执行,即使多个事务同时请求修改同一数据,也只有一个事务能够执行,避免了幻读的问题,但可能会降低数据库的并发性能。
不同的隔离级别会对数据库的性能和数据的完整性产生不同的影响,开发人员应该根据应用的需求选择合适的隔离级别。通常来说,读已提交和可重复读是应用最广泛的两个隔离级别,可以满足大部分应用的需求。