数据库事务详解
提示:事务主要是为了保证复杂数据库操作数据的一致性,尤其是在并发访问数据时。MySQL事务主要用于处理操作量大,复杂度高的数据。
一、什么是数据库事务?
从根本上理解MySQL事务,是指作为单个逻辑工作单元执行的一系列操作,要么成功完全地执行,要么失败全部回滚。
最经典的例子:
用户A往——》用户B账户里转100块钱。
正常逻辑:首先用户A账户里扣除一百元,然后用户B账户增加100元,则转账操作完成。这是正常情况,接下来再看看这种情况:
用户A账户里扣除100元,这条操作语句执行完了,正要执行用户B账户增加100元,这时候突然系统出问题了,宕机了程序没有按流程接着往下走。这时候用户A账户里少了100,可用户B账户里却没有增加100。那这怎么办呢? 这时候就该用到事务了。
上面说过,作为单个逻辑工作单元执行的一系列操作,要么成功完全地执行,要么失败全部回滚。系统要么全部给我走完,要么执行到一半失败了进行回滚:用户A账户里扣了100元,准备往用户B账户里加100元的时候出问题了,好嘛,出问题了就出问题了嘛,我再回滚给用户A账户里加会100元不就好了嘛。
二、事务有哪些状态?
事务一共分为五个状态:
-
活动的 ( active ) 事务对应的数据库操作再执行过程中,该事务就处于活动的状态。
-
部分提交的 ( partially committed ) 当数据库事务中的最后一个操作执行完成,但由于操作都在内存中执行,所以造成的影响并没有更新到磁盘时,该事务就处在部分提交的状态。
-
失败的 ( failed ) 当事务处在活动的或者部分提交状态时,可能遇到了某些错误(数据库自身的错误,操作系统错误或者直接断电)而无法继续执行,或者认为的停止当前事务的执行,该事务就处在失败的状态。
-
中止的 ( aborted ) 如果事务执行了半截而变成失败的状态,撤销失败事务对当前数据库造成的影响,我们把这个撤销的过程称之为回滚。 当回滚的操作执行完毕,也就是数据库恢复到了执行事务之前的状态,该事务就会处于终止的状态。
-
提交的 ( committed ) 当一个处在部分提交的状态事务将修改过的数据都同步到磁盘之后,该事务就处于提交的状态。
三、事务有哪些特性?
事务共有四大特性:
1.原子性( Atomicity)
事务的数据操作,要么全部执行成功,要么全部失败回滚到执行之前的状态,就像这个事务从来没有执行过一样。事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
2.一致性( Atomicity)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。一致性处理数据库中对所有语义约束的保护。假如数据库的状态满足所有的完整性约束,就说该数据库是一致的。例如,当数据库处于一致性状态S1时,对数据库执行一个事务,在事务执行期间假定数据库的状态是不一致的,当事务执行结束时,数据库处在一致性状态S2。
3.隔离性 ( Consistency)
多个事务之前是相互隔离的,互不影响。数据库允许多个并发同时对其数据进行读写和修改,隔离性可以防止多个事务并发执行时由于交叉执行而导致的数据不一致。
比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
隔离性分为四个隔离级别:
-
读未提交(Read Uncommitted):
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。该隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少,而且还会出现脏读的情况。读取到未提交的数据,也被称之为脏读(Dirty Read)。 -
读已提交(Read Committed):
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。但会出现以下情况:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。 -
可重复读(Repeatable Read):
读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他读事务。避免了不可重复读和脏读,但是会出现幻读,即第二次查询数据时会包含第一次查询中未出现的数据。避免了不可重复读取和脏读,但是有时可能出现幻读。这可以通过“共享读锁”和“排他写锁”实现(MySQL默认的隔离级别)。 -
序列化(Serializable):
当执行某个事务的时候,禁止其他任何事务运行,必须一个一个进行。提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读。
四种事务隔离级别从上往下,级别越高,并发性越差,安全性就越来越高。 MySQL默认隔离级别是可重复读。
4.持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
持久性意味着当系统或介质发生故障时,确保已提交事务的更新不能丢失。即对已提交事务的更新能恢复。一旦一个事务被提交,DBMS(数据库)必须保证提供适当的冗余,使其耐得住系统的故障。所以,持久性主要在于DBMS的恢复性能。
四、事务是如何实现的
事物是通过事物日志来实现的,事物日志包括:redo log和undo log;
redo log 是重做日志:
重做日志是每当有操作执行前,将数据真正更改时,先前相关操作写入重做日志。这样当断电,或者一些意外,导致后续任务无法完成时,系统恢复后,可以继续完成这些更改。
undo log 是回滚日志
回滚日志是当一些事务在执行一半时,发生意外,导致后续操作无法完成,则可以根据回滚日志恢复到执行该事务之前的壮态。
另外推荐一篇sql语法调优文章,希望对各位小伙伴能有所提升!