MySQL的四大特性
MySQL数据库有原⼦性(Atomicity)、⼀致性(Consistency)、隔离性(Isolation)和持久性(Durability)四大特性。
原子性
原子性确保数据库事务是不可分割的工作单位。事务中的所有操作要么全部执行成功,要么全部不执行,不会部分执行。如果事务中的任何一部分失败,整个事务就会被回滚,好像从未开始过一样。
例子
情人节我向女朋友转账520元,如果转账成功了,那么我的余额就会减少520元,我女朋友的账户余额会增加520元。如果发生某种错误,转账未成功,那么我转账这件事就会回滚到我没发起转账的状态,我的余额不会因为女朋友没有收到而少去520.
如何保证原子性?
主要是利⽤undo log(回滚⽇志),回滚日志记录事务执行前数据的状态,以便在事务需要回滚时,能够撤销已执行的操作,恢复数据库到事务开始前的状态。
例如:
- delete⼀条数据的时候,就需要记录这条数据的信息,回滚的时候,insert这条旧数据
- update⼀条数据的时候,就需要记录之前的旧值,回滚的时候,根据旧值执⾏update操作
- insert⼀条数据的时候,就需要这条记录的主键,回滚的时候,根据主键执⾏delete操作
分布式数据库如何保证原子性?
(埋坑)
一致性
一致性保证事务执行前后,数据库从一个一致的状态转变为另一个一致的状态。即使在事务执行期间系统出现故障,数据库也必须保持在一个有效且符合预期的状态中。所谓一致性,就是数据符合我们对它的某些限制。比如,我转账的钱 = 我女朋友收到的钱。
如何保证一致性?
分为两个层⾯来说。
- 从数据库层⾯,数据库通过原⼦性、隔离性、持久性来保证⼀致性。也就是说ACID四⼤特性之中,C(⼀致性)是⽬的,A(原⼦性)、I(隔离性)、D(持久性)是⼿段,是为了保证⼀致性,数据库提供的⼿段。数据库必须要实现AID三⼤特性,才有可能实现⼀致性。例如,原⼦性⽆法保证,显然⼀致性也⽆法保证。
- 从应⽤层⾯,通过代码判断数据库数据是否有效,然后决定回滚还是提交数据!
隔离性
隔离性要求并发执行的事务之间互不干扰。每个事务都感觉像是在单独访问数据库一样,这样可以防止事务之间的读写冲突,保证事务结果的正确性。不同的隔离级别(如读未提交、读已提交、可重复读、串行化)提供了不同程度的隔离保证。
如果无法保证隔离性会发生什么?
脏读
一个事务可以读取到另一个事务尚未提交的数据。如果后者最终回滚了其更改,那么前者读取到的数据就是无效的,这可能导致错误的业务决策或数据不一致。读到了无效数据!
不可重复读
在同一事务中,如果两次读取同一数据,可能会得到不同的结果,因为其他事务在这两次读取之间已经修改并提交了该数据。这违反了用户对数据稳定性的期望。前后两次发生了数据的修改!
幻读
在一个事务内,多次执行同一条查询语句,每次返回的结果集可能会有差异,原因是有其他事务在这期间向表中插入了新行,导致原本不满足条件的记录出现在结果集中。这对于依赖特定数据集合进行计算或判断的事务来说是个问题。前后两次发生了数据的增加或删除!
如何保证隔离性?
- 提供事务隔离级别
- 读未提交(Read Uncommitted):事务可以读取其他未提交事务修改的数据,可能导致脏读。
- 读已提交(Read Committed):事务只能读取其他已提交事务的结果,避免了脏读,但可能出现不可重复读。
- 可重复读(Repeatable Read):在一个事务内多次读取同一条数据结果是一样的,避免了不可重复读,但可能遇到幻读问题。
- 串行化(Serializable):最严格的隔离级别,通过串行执行事务或者使用更高级的锁机制来避免所有并发问题,包括脏读、不可重复读和幻读,但性能开销最大。
- 并发控制
- 锁机制:包括行锁、表锁、页锁等。通过在事务访问数据前加锁,阻止其他事务修改或读取,直到当前事务结束释放锁。锁的类型和粒度会影响并发性能。
- 多版本并发控制(MVCC, Multiversion Concurrency Control):允许多个事务读取同一份数据的不同版本,而不会相互阻塞。每个事务看到的是基于事务开始时刻数据的一个快照,从而避免了读写冲突,广泛应用于如PostgreSQL、MySQL的InnoDB引擎中。
- 时间戳排序:为事务分配时间戳,事务按照时间戳顺序执行,以避免冲突。
- 乐观锁与悲观锁:乐观锁假设并发冲突较少,仅在提交时检查数据是否被修改;悲观锁则假定会发生并发冲突,提前加锁防止修改。
持久性
持久性意味着一旦事务被提交,它引起的数据变化就会永久保存在数据库中,即使发生系统崩溃或电源故障等意外情况,这些改变也不会丢失。
如何保证持久性?
持久性主要通过redo log(重做日志)来实现。每当数据库中的数据发生变化时,数据库系统首先将这些变化记录到事务日志中。事务日志通常是顺序写入磁盘上的非易失性存储介质(如HDD或SSD),以确保即使在系统崩溃或电源故障的情况下,数据的修改操作仍能被追踪并恢复。在事务提交前,其相关日志会被标记为“已准备好提交”。如果发生故障,系统重启后可以通过重做(redo)日志将未完全写入数据库的数据操作完成,从而恢复到一致状态。
意外情况
在MySQL中,为了解决CPU和磁盘速度不⼀致问题,MySQL是将磁盘上的数据加载到内存,对内存进⾏操作,然后再回写磁盘。假设宕机了,在内存中修改的数据全部丢失了,持久性就⽆法保证。
怎么解决?
使用预写日志!在实际修改数据库之前,先将修改记录写入日志中。这样即使在修改数据和更新内存与磁盘之间发生故障,也能根据日志恢复到一致状态。
标签:事务,隔离,数据库,回滚,特性,保证,MySQL,数据 From: https://blog.csdn.net/weixin_51332735/article/details/139112558