事务
概念
数据库中的事务是指对数据库执行一批操作,在同一个事务当中,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。
一个最经典的例子就是A有500元,B有100元,A给B转钱100元,那么数据库中最后的数据是A变成400元,B变成200元。但是假设一些原因,A给B转的100元没有成功,如果数据没有回滚,那么就会造成A变成400元,B还是100元,这种情况我们需要避免而不是减少,因此需要数据库事务。
事务的ACID原则
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
注意:以上的原则是我们在编写事务流程中必须要注意的点,事务是必须满足ACID原则。
一个事务的例子(MySQL)
如图1所示,就是一个最简单的事务,需要注意的是,MySQL的存储引擎是Innodb,它是支持事务和外键约束的,像MYSAM就不支持事务。
另外,需要注意,rollback;指令不代表数据是错的,有时候我们需要将数据回滚到最初的位置,比如在用户填写完很多数据后突然返回了点击重置,我们就可以在数据库层来操作数据回滚。但是,我不推荐在数据库做大量的逻辑,因为数据库就是来存储和读取数据的,我们需要将自己的逻辑放在业务层或者前端去实现。
图1 . 一个最简单的事务
事务的隔离级别
命令
在MySQL中,我们可以通过一个命令去查看当前的隔离级别如图2
select @@global.TRANSACTION_isolation, @@TRANSACTION_isolation;
图2. 查看当前事务的隔离级别
隔离级别带来的问题
脏读
一个事务在执行的过程中读取到了其他事务还没有提交的数据。
读已提交
从字面上我们就可以理解,即一个事务操作过程中可以读取到其他事务已经提交的数据。
不可重复读
在同一事务中,多次读取同一数据返回的结果有所不同,换句话说,后续读取可以读到另一事务已提交的更新数据。相反,“可重复读” 在同一事务中多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据。
可重复读
一个事务操作中对于一个读取操作不管多少次,读取到的结果都是一样的。
幻读
事务A在操作一堆数据的时候,事务B插入了一条数据,A事务再次(第二次)查询,发现多了一条数据,像是幻觉。与不可重复读类似,不同的是一个是修改删除操作,一个是新增操作。
各种隔离级别出现的问题
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
只读未提交 | 是 | 是 | 是 |
不可重复读 | 否 | 是 | 是 |
可重复读 | 否 | 否 | 是 |
序列化 | 否 | 否 | 否 |
注意:这个是在面试中很容易问到的问题,如果没有理解透彻,先把这张表记下来。
总结
因为我对数据库的理解也只是表面,所以这部分内容我总结的比较少,那么作为java后端为什么要学数据库的基本操作呢,是因为有些框架比如Mybaitis是需要我们手写SQL语句的,因此理解基本的数据库知识很重要。