MySQL的四⼤特性

MySQL数据库有原⼦性(Atomicity)、⼀致性(Consistency)、隔离性(Isolation)和持久性(Durability)四大特性。

原子性

原子性确保数据库事务是不可分割的工作单位。事务中的所有操作要么全部执行成功,要么全部不执行,不会部分执行。如果事务中的任何一部分失败,整个事务就会被回滚,好像从未开始过一样。

例子

情人节我向女朋友转账520元,如果转账成功了,那么我的余额就会减少520元,我女朋友的账户余额会增加520元。如果发生某种错误,转账未成功,那么我转账这件事就会回滚到我没发起转账的状态,我的余额不会因为女朋友没有收到而少去520.

如何保证原子性?

主要是利⽤undo log(回滚⽇志),回滚日志记录事务执行前数据的状态,以便在事务需要回滚时,能够撤销已执行的操作,恢复数据库到事务开始前的状态。
例如:

  • delete⼀条数据的时候,就需要记录这条数据的信息,回滚的时候,insert这条旧数据
  • update⼀条数据的时候,就需要记录之前的旧值,回滚的时候,根据旧值执⾏update操作
  • insert⼀条数据的时候,就需要这条记录的主键,回滚的时候,根据主键执⾏delete操作

分布式数据库如何保证原子性?

(埋坑)

一致性

一致性保证事务执行前后,数据库从一个一致的状态转变为另一个一致的状态。即使在事务执行期间系统出现故障,数据库也必须保持在一个有效且符合预期的状态中。所谓一致性,就是数据符合我们对它的某些限制。比如,我转账的钱 = 我女朋友收到的钱。

如何保证一致性?

分为两个层⾯来说。

  • 从数据库层⾯,数据库通过原⼦性、隔离性、持久性来保证⼀致性。也就是说ACID四⼤特性之中,C(⼀致性)是⽬的,A(原⼦性)、I(隔离性)、D(持久性)是⼿段,是为了保证⼀致性,数据库提供的⼿段。数据库必须要实现AID三⼤特性,才有可能实现⼀致性。例如,原⼦性⽆法保证,显然⼀致性也⽆法保证。
  • 从应⽤层⾯,通过代码判断数据库数据是否有效,然后决定回滚还是提交数据!

隔离性

隔离性要求并发执行的事务之间互不干扰。每个事务都感觉像是在单独访问数据库一样,这样可以防止事务之间的读写冲突,保证事务结果的正确性。不同的隔离级别(如读未提交、读已提交、可重复读、串行化)提供了不同程度的隔离保证。

如果无法保证隔离性会发生什么?

脏读

一个事务可以读取到另一个事务尚未提交的数据。如果后者最终回滚了其更改,那么前者读取到的数据就是无效的,这可能导致错误的业务决策或数据不一致。读到了无效数据!

不可重复读

在同一事务中,如果两次读取同一数据,可能会得到不同的结果,因为其他事务在这两次读取之间已经修改并提交了该数据。这违反了用户对数据稳定性的期望。前后两次发生了数据的修改!

幻读

在一个事务内,多次执行同一条查询语句,每次返回的结果集可能会有差异,原因是有其他事务在这期间向表中插入了新行,导致原本不满足条件的记录出现在结果集中。这对于依赖特定数据集合进行计算或判断的事务来说是个问题。前后两次发生了数据的增加或删除!

如何保证隔离性?

  1. 提供事务隔离级别
  • 读未提交(Read Uncommitted):事务可以读取其他未提交事务修改的数据,可能导致脏读。
  • 读已提交(Read Committed):事务只能读取其他已提交事务的结果,避免了脏读,但可能出现不可重复读
  • 可重复读(Repeatable Read):在一个事务内多次读取同一条数据结果是一样的,避免了不可重复读,但可能遇到幻读问题。
  • 串行化(Serializable):最严格的隔离级别,通过串行执行事务或者使用更高级的锁机制来避免所有并发问题,包括脏读、不可重复读和幻读,但性能开销最大。
  1. 并发控制
  • 锁机制:包括行锁、表锁、页锁等。通过在事务访问数据前加锁,阻止其他事务修改或读取,直到当前事务结束释放锁。锁的类型和粒度会影响并发性能。
  • 多版本并发控制(MVCC, Multiversion Concurrency Control):允许多个事务读取同一份数据的不同版本,而不会相互阻塞。每个事务看到的是基于事务开始时刻数据的一个快照,从而避免了读写冲突,广泛应用于如PostgreSQL、MySQL的InnoDB引擎中。
  • 时间戳排序:为事务分配时间戳,事务按照时间戳顺序执行,以避免冲突。
  • 乐观锁与悲观锁:乐观锁假设并发冲突较少,仅在提交时检查数据是否被修改;悲观锁则假定会发生并发冲突,提前加锁防止修改。

持久性

持久性意味着一旦事务被提交,它引起的数据变化就会永久保存在数据库中,即使发生系统崩溃或电源故障等意外情况,这些改变也不会丢失。

如何保证持久性?

持久性主要通过redo log(重做日志)来实现。每当数据库中的数据发生变化时,数据库系统首先将这些变化记录到事务日志中。事务日志通常是顺序写入磁盘上的非易失性存储介质(如HDD或SSD),以确保即使在系统崩溃或电源故障的情况下,数据的修改操作仍能被追踪并恢复。在事务提交前,其相关日志会被标记为“已准备好提交”。如果发生故障,系统重启后可以通过重做(redo)日志将未完全写入数据库的数据操作完成,从而恢复到一致状态。

意外情况

在MySQL中,为了解决CPU和磁盘速度不⼀致问题,MySQL是将磁盘上的数据加载到内存,对内存进⾏操作,然后再回写磁盘。假设宕机了,在内存中修改的数据全部丢失了,持久性就⽆法保证。

怎么解决?

使用预写日志!在实际修改数据库之前,先将修改记录写入日志中。这样即使在修改数据和更新内存与磁盘之间发生故障,也能根据日志恢复到一致状态。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值