zoukankan      html  css  js  c++  java
  • 数据库事务

    引言

    相信没有哪个程序员会不知道事务,而且面试中对事务的考察如同朋友见面打个招呼般是再平常不过的事情了。这样给你说吧,事务是程序员“居家旅游”必备技能。如果你学完 JavaSE,仍然对事务一无所知或一知半解,那你得赶紧补一补事务啦。

    你可能会想,事务真有那么重要吗?我不知道事务不也一样写代码呀。如果你看完这篇关于事务的文章,我相信你就明白为何事务非常重要了。

    事务的产生

    假如有一天,你的一个好朋友找你借一笔钱,说是准备买房子,差点钱付首付。你是一个很讲义气的人,所以二话不说就同意了。然后,你让他告诉你卡号,准备通过手机银行转账。

    这时,我们想一想银行转账业务的流程是不是应该如下:

    1. 查看我的银行账号,看里面的钱够不够转账(如果不够直接提示余额不足)

    2. 从我的银行账号上扣掉一笔钱

    3. 在我朋友的银行账号上添加一笔钱

    4. 通知双方转账成功

    那么,我们再想一想,转账业务的整个流程需要操作数据库多少次(或者写多少条 SQL 语句)

    是不是一共三条呀,如下:

    1. 第一条 SQL 语句是查询我的账号

    2. 第二条 SQL 语句是从我的账号上扣钱

    3. 第三条 SQL 语句是从我朋友的账号上加钱

    好像这一切都没有问题,那么这和事务有什么关系呀。

    先别着急嘛,假设,我是说假设,当程序在执行第二条 SQL 语句刚完成(也就是我的账号上的钱已经从数据库里扣掉了),还没来得及执行第三条 SQL 语句时(也就是给我朋友账号上的钱还没从数据库里加上),结果程序就出现异常,崩溃了。

    想一想这时会是怎样的一个结果。

    结果就是我账号上的钱是真的扣掉了,但是朋友账号上的钱却一分没有加上。

    还有这种事情呀,可能你重来没有遇到过,也没听说过。那我告诉你原因,这是因为有事务的存在,否则上面的情况是完全可能出现的,估计那时银行的门都会被挤破,呵呵。

    这样看来,事务确实很重要。废话,没有事务,很多程序、很多业务都可能出问题哈。

    那事务究竟是什么,到底有何魔力,为何说能够搞定上面转账可能遇到的问题呢?

    什么是事务

    事务就是用户定义的一系列数据库操作,这些操作可以视为一个完成的逻辑处理工作单元,要么全部执行,要么全部不执行,是不可分割的工作单元。

    说人话就是,事务是把一系列操作数据库的 SQL 语句打包在一起执行,执行事务只有两个结果:要么所有 SQL 语句都执行成功,要么 所有 SQL 语句一条都不执行。

    • 第一个结果,所有 SQL 语句都执行成功。这个很好理解哈,就是不出现任何异常嘛。

    • 第二个结果,所有 SQL 语句全部都不执行。意思也很简单,就拿上面转账的例子来说,假设出现异常导致第三条 SQL 语句没执行的情况,如果这三条 SQL 语句打包放在一个事务中,这时事务会让之前执行过的前两条 SQL 语句恢复到没有执行时的状态,这在事务中称为事务回滚。事务回滚后,意味着这三条 SQL 语句一条也没执行过,数据库的数据还是转账前的数据,你既没有扣钱,你朋友也没有加钱,什么都没有变哈。

    事务的四个属性(ACID)

    搞明白事务的概念,我们还需要掌握事务的四个属性,这在面试中是要求能够说出或写出,还要能够解释清楚每个属性的含义哈。

    首先,事务的四个属性分别是原子性、一致性、隔离性、持久性。接着,我分别给大家解释这四个属性的含义。

    原子性(Atomicity)

    原子性是最好理解的,这个属性是事务最基本的属性,从事务的概念中也体现出了事务的原子性。一想到原子给人的感觉就是很小,小到不可分割,所以所谓原子性,就是指事务打包的一系列 SQL 语句,是不可分割的,是一个整体;要么全部执行成功,要么有一个失败就事务回滚,全部不执行哈。

    一致性(Consistency)

    一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。就拿转账的例子来说,要么转账失败,要么转账成功,不允许成功了一半的情况哈。也就是说,只有转账成功(三条 SQL 语句都全部执行),数据库的数据才会改变。也不是说,不可能出现我账号上的钱扣除成功了,结果朋友账号的钱没有增加的情况,这就不符合事务的一致性哈。

    隔离性(Isolation)

    隔离性是当多个用户同时并发访问数据库时,比如同时操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

    怎么理解事务的隔离性呢,想一想如果有两个事务,它们都要操作数据库,更巧的是它们不仅是同时操作数据库(并发),而且操作的还是数据库的同一张表的同一条数据。

    你可能会想,怎么可能有这种情况呀,我告诉你当用户多了,也就是高并发的情况下,这种情况是很有可能发生的哈。我们知道,事务是打包一系列 SQL 语句。

    现在有两个事务同时在执行一系列 SQL 语句,而且又是操作的是同一张表的同一个数据,那么这会出现什么结果呢。会不会两个事务相互影响,相互干扰,你把数据改过来,我又把数据改过去。如果真是这样,岂不违背了前的说的事务的一致性了。

    所以,事务的隔离性专门用于解决以上问题,以确保事务之间相互隔离,互不干扰。

    那如何解决的呢,简单理解就是加锁,也就是当一个事务操作数据库的数据给数据加上锁,如果有其它事务同时也要操作数据库的相同数据时就必须排队等待,等加锁的事务完事了,把锁释放掉以后,才能进行数据库操作。

    关于事务的隔离性,一般数据库会提供了很多种隔离级别,感兴趣的童靴可以看我专门关于隔离级别的介绍文章哈。

    持久性(Durability)

    持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

    之前转账的例子,我们说当程序在执行完第二条 SQL 语句就可能出现异常崩溃了,那么试想一下数据库也可能有出现故障的情况呀。如果正在执行事务的过程中,程序没有出现异常,而是数据库出现故障了,这会如何呀。

    答案是程序一旦调用 commit 方法将事务提交给数据库,那它对数据库的改变将是永久性的,因为数据已经写进了物理磁盘了,即使数据库出现故障也不会对数据产生任何影响。相信你应该明白,数据库存储的数据是放在磁盘里的,所以即使关机断电也可以持久保存哈。

    总结

    • 事务就是将一系列 SQL 语句打包一起执行,要么全部执行成功,要么一条都没执行;

    • 事务的四大属性(ACID):原子性、一致性、隔离性、持久性。

    作者:Binge
    本文版权归作者和博客园共有,转载必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    Servlet监听器及在线用户
    数据分页jdbc+mysql实现
    使用ajax验证用户名重复
    Mysql中的事务
    用户登录注册案例分析
    Java连接mysql数据库
    Java连接sqlite数据库
    虚拟主机TOMCAT配置
    用jquery控制表格奇偶行及活动行颜色
    JDK安装后 没有tools.jar 和dt.jar包的解决办法
  • 原文地址:https://www.cnblogs.com/binbingg/p/13767437.html
Copyright © 2011-2022 走看看