数据库-事务管理详解

什么是事务?

一个事务的存在价值是保证一系列数据操作的同时执行,例如转账和收款就可以被包装成一个事务,如果两者不是一个事务,那就可能导致转账数据成功(数据减少),但收账数据错误,没有收账成功,这样钱就凭空消失了,而有了事务的参与,两者只能一同成功或失败,便可以避免这问题。

事务是sql语句执行的过程,任何的sql语句都是一个事务,只不过我们默认开始自动提交,所以我们如果不关闭自动提交,那么每个sql语句都不会等待下个sql语句,而是直接修改数据库,而我们可以通过命令暂时停止自动提交,或停止本次会话的自动提交等方式,创造一个多sql语句的事务,那么本次事务中的sql语句将会把修改后的内容先保存起来,等待commit命令一起修改数据库。

那么整个事务是如何保存修改信息,统一更改数据的呢?

要了解这个,首先我们要知道数据库是如何被访问和修改的,首先对于数据库管理软件(如mysql,orcale等),他们对于数据的管理是基于分页的,什么是分页,它类似于操作系统对于内存的分页管理一样,数据库管理软件将他们要保存的信息分成若干个数据页(如mysql每个数据页是16kb),而数据库管理系统只需记录这写页的地址而无需记录每个数据的地址。

当我们有修改或访问数据的操作时,对应数据页会被加载到内存中供我们读取和修改,并且会长时间保存在数据库缓冲区(后面会讲如何回收),这加快了我们访问数据库的速度。而我们对于数据的修改操作实际上是会先修改内存中数据页的内容,然后等待commit指令再将数据页的内容修改到硬盘中,这便是完整的一个事务修改数据库的过程。

事务隔离级别

什么叫事务隔离?当我们对于数据页进程修改吗,但未提交的过程中,可能有多个事务在对这个数据页同时进行操作,如何处理这些事务之间的关系,这就是事务隔离。

事务隔离的等级有四个

1.读未提交(read uncommitted )

读未提交是指,当另一个事务对一个数据页的内容进行修改但不提交时,本次事务如果他的隔离等级设置是读未提交,那么他在对这个数据页进行访问时,便会访问到另一个事务修改但未提交的数据

2.读已提交(read committed )

读已提交是指,,当另一个事务对一个数据页的内容进行修改但不提交时,本次事务如果他的隔离等级设置是读已提交,那么他在对这个数据页进行访问时,便会访问到修改前的数据,那么问题来了,一个数据页,为什么它能保存修改前和修改后的两种数据?

实际上,一个数据页可以保存多个版本数据,他会自己进行版本控制,而具体保存多少版本数据取决于有多少事务正在修改或查询这个版本的数据,当没有任何事务在访问他的早期版本数据时,那么理论上他只会保存一个当前版本数据,以及一个修改未提交的数据(这个版本控制是针对于数据而非数据页,也就是说两个版本实际上是在一个数据页中,而不是两个数据页,两个版本,这也最大限度的节约了内存)。

那么当一个读已提交的隔离等级的事务在访问数据页时,便不会读取后的版本,而是修改前的版本。

3.可重复读(repeatable read )

可重复读值得是,当一个事务读取一个数据页时,多次读取数据保持一致,即使其他事务在当前事务两次读取操作之间修改了数据页内容,第二次读取也仍然会与第一次读取数据保持一致。经过上面讲解的版本控制,我们也可以猜到,其实这个隔离等级的本质操作就是保证两次读取的数据版本一致。(可重复读的隔离等级包含读已提交)

4.串行化(serializable )

串行化就是说,本次事务的一切操作都必须保证没有其他事务操作此数据页的情况下进行,只要有其他事务在操作这个数据页,就必须等待其他事务commit。

数据页的回收机制

为了更好的数据库访问性能,数据页通常会保存在数据库缓冲区中以达到更快的访问速度,与此同时,数据页的回收机制也必不可少。

在正常情况下,数据库管理软件会将长时间没有访问的数据页进行回收,而当数据库缓存区过载时,数据页的回收便会稍微复杂。

首先他会根据一系列算法去计算当前最合适被回收的数据页是哪个,其中包括数据也使用频率以及数据页创建时间等因素的比较,当回收页涉及正在被事务修改而没有commit的数据页时,数据库管理软件通常有两种解决办法

1.传统办法

他会将整个数据页的所有版本数据全部保存在硬盘中,也就是说硬盘中保存的数据库元数据除了他本身的数据,还有未提交版本的数据,这样做的优势是性能更高,直接将结果修改到元数据中,并且利用了尽可能少的空间保存数据页内容,确定是不够安全,因为直接将未修改完全的数据保存到元数据中,数据错综复杂,出现问题难以修复

2.写时复制

他会在磁盘中使用新的空间防止这未操作完成的数据页不会修改元数据,并且下次操作时重新加载到内存中,这样保证了数据的安全性,但也浪费的空间和性能

事务隔离解决了什么问题?

1.脏读

脏读表示一个事务读取了另一个事务修改但是未提交的数据表示脏读(读已提交,可重复读,串行化都解决了这个问题)

2.不可重复读

不可重复读是指两次读取数据不一致(可重复读,串行化解决了这个问题)

3.幻读

幻读值得是保证在读取过程中数据量不会增加或减少(串行化解决了这个问题,不过串行化解决的不是本次事务自己的问题,而是他通过不和其他事务一起执行,保证了其他事务不会幻读)

简单的事务相关命令

#简单的相关命令

#单次开启长事务
start transaction;
sql命令;
sql命令;
commit;

#查看当前自动提交状态
show variables like '%commit%';
#关闭自动提交
set autocommit = 0;
sql命令
sql命令
commit

#查看当前事务隔离等级
select @@tx_isolation;
#设置隔离等级
set session transaction isolation level  隔离级别;

  • 14
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不止会JS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值