前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据库隔离级别

数据库隔离级别

原创
作者头像
写bug的高哈哈
发布2024-11-08 13:35:44
140
发布2024-11-08 13:35:44

在阅读《高性能MySQL》这本书的过程中,我复习了一下关于数据库事务中“隔离性”的章节。回想起来,在大学数据库系统课程中应该学过这一部分内容,但现在确实记不清了。数据库中的事务是一种机制,允许连续执行一组SQL指令,如果在执行这一系列指令的过程中出现任何错误,整个事务将会回滚至最初的状态,以此保证事务要么整体成功,要么整体失败,不会出现部分成功、部分失败的情况。

举例来说,假设有两张银行账户表,分别记录了Alice和Bob各自的账户余额,初始状态下两人都有1000元。

现在Alice转账300元给Bob,正常的操作流程应该是执行两条SQL语句:

代码语言:sql
复制
UPDATE balances SET balance = 700 WHERE account = "Alice";
UPDATE balances SET balance = 1300 WHERE account = "Bob"; 

在执行第一行操作时,如果系统出现问题导致未能执行第二行操作,这样会出现Alice的钱被扣除,而Bob的账户却没有增加相应金额的情况。这种错误发生后修复起来会非常麻烦。为此,数据库中的事务(Transaction)机制就是为了解决这类问题而设计的,它可以确保一个交易要么全部成功,要么全部失败,绝不会停留在中间状态。

在SQL中,可以声明事务的开始和结束,并在必要时回滚到原始状态,这样就能有效避免上述问题的发生。通过使用事务,当涉及到诸如银行转账(如从Alice账户扣款并转入Bob账户)这样的操作时,可以确保资金变动要么全部完成,要么都不发生,以此来维护数据库的一致性和完整性。

代码语言:sql
复制
BEGIN TRANSACTION;
UPDATE balances SET balance = 700 WHERE account = "Alice";
UPDATE balances SET balance = 1300 WHERE account = "Bob";
COMMIT;

关系型数据库在处理事务时通常要求具备四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),即ACID原则。今天我们主要讨论的是“隔离性”。隔离性确保在系统中有多个事务同时执行时,每个事务之间互不影响。

以下是关于隔离性经常会遇到的几种现象,图表中的Y轴代表时间顺序。

脏读(Dirty Read)

如果一个事务还未提交,但其他事务却能读取到它已更新但尚未提交的数据,这种情况称为脏读。例如,事务A在执行过程中两次读取Alice的账户余额,第一次读取时数值为1000,但在事务A未结束前,另一个事务B改变了Alice的账户余额为700,但尚未提交。这时事务A再次读取Alice的余额,读取到了尚未提交的700元,这就是脏读。

不可重复读(Non-repeatable reads)

在同一事务内,即使使用相同的查询语句多次读取数据,结果却发生了变化,这种情况称为不可重复读。例如,事务A第一次读取到Alice的账户余额为1000,在事务A还未结束时,事务B修改了Alice的余额为700并提交了事务。随后事务A再次执行相同的查询,这次读取到的余额变为700,这就构成了不可重复读。请注意,脏读也是不可重复读的一种特殊情况。

幻读(Phantom reads)

在同一个事务内连续两次执行同样的查询条件,但返回的记录数量却不一致,这种现象称为幻读。举例说明,事务A第一次查询账户余额在900到1000元范围内的账户,结果显示有Alice和Bob两人。而在事务A还未结束的同时,事务B将Alice的余额更新为700元。此时,如果事务A再次基于相同的条件查询,结果中的记录数会从原来的2条减至1条,这就发生了幻读。

隔离级别

针对上述提到的三种问题,SQL中通过不同的隔离等级来确定哪种等级的隔离性可以解决相应问题。隔离等级共有四种:

  • 读未提交(Read Uncommitted):在这种隔离等级下,事务可以读取到其他事务未提交的数据,所以在此等级下,上述三种问题都没有得到解决。
  • 读已提交(Read Committed):事务只能读取到其他事务已提交的数据,未提交的数据不会被读取,因此在这个等级中解决了脏读问题。
  • 可重复读(Repeatable Read):在一个事务中,只要查询条件相同,每次读取特定字段的数据都会得到相同的结果,这一等级解决了不可重复读问题。
  • 序列化(Serializable):在多个事务并发执行时,只要事务的执行顺序相同,无论何时执行都会得到相同的结果。例如,先执行事务A再执行事务B,在相同的条件下,每次执行都将产生一样的结果。在这个最高的隔离等级下,除了不可重复读之外,连幻读问题也会被一并解决。

顺便提及,MySQL的默认隔离等级是可重复读,但可以通过以下命令调整为序列化:

代码语言:sql
复制
SET SESSION transaction_isolation='SERIALIZABLE';

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 脏读(Dirty Read)
  • 不可重复读(Non-repeatable reads)
  • 幻读(Phantom reads)
  • 隔离级别
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档