Fork me on GitHub

MySQL事务及其四个特性

事务概念引入

    现实生活中,我们往往经常会进行转账操作,转账操作可以分为两部分来完成,转入和转出。只有这两部分都完成了才可以认为是转账成功。在数据库中,这个过程是使用两条语句来完成的,如果其中任意一条语句出现了异常没有执行,则会导致两个账号的金额不同步,造成错误。
     为了防止上面可能出现的情况,MySQL引入了事务,所谓事务就是针对数据库的一组操作,它可以由一条或多条SQL语句组成,同一个事务的操作具备同步的特点,如果其中有一条语句不能执行的话,那么所有的语句都不会执行,也就是说,事务中的语句要么都执行,要么都不执行。

    在使用数据库时候需要使用事务,必须先开启事务,开启事务的语句具体如下:
start transaction;
即:
1
上面语句是用来开启事务,事务开启之后就可以执行SQL语句,SQL语句执行成功之后,需要使用相应语句提交事务,提交事务的语句如下:
commit;
需要注意的是,在MySQL中直接书写SQL语句都是自动提交的,而事务中的操作语句需要使用commit语句手动提交,只有事务提交后其中的操作才会生效。
如果不想提交事务,我们还可以使用相关语句取消事务(也称回滚),具体语句如下:
rollback;
注: rollback语句只能针对未提交的事务执行的回滚操作,已经提交的事务是不能回滚的。

事务的四个基本要素(ACID)

ACID,指数据库事务正确执行的四个基本要素的缩写。包含: 原子性一致性隔离性持久性

1
2
3
4
原子性: 原子性意味着事务的整体性和不可分割性,这就类似化学中的原子,是一个不可分割的单元。一个事务可以是一个(任务)操作,也可以是多个(任务)操作,假设一个事务由多个操作(任务)组成,那么这些操作必须都执行成功这个事务才被认为执行成功,只要其中有一个任务执行失败那么整个事务都会被认为执行失败,导致自动回滚到初始状态,通俗来讲就是“同进退”,这保证了事务的整体性。这就是事物的原子性。 专业来讲,原子的执行是一个全部发生或全部失败的整体过程。在一个原子操作中,如果事务中的任何一个语句失败,前面执行的语句都将被返回,以保证数据的整体性不被破坏。这在常用的系统应用中,为保证数据的安全性起到一定作用。
一致性: 在MySql事务处理过程中,无论事务是完全成功或是在中途因某些环节失败而导致失败,但事务使系统处于一致的状态时,必须保持一致性,用户A向用户B的账户中转入5000元,但用户B在查询转账信息的时候,发现自己的账户只增加了3000元,这样不能使整个事务达到一致性。 在MySql中,一致性主要由MySql的日志机制处理,它记录数据库的所有变化,为事务回复提供跟踪记录。如果系统在事务处理中间发生错误,MySql恢复过程将使用这些日志发现事务是否已经完全成功执行或需要返回。一致性属性保证数据库从不返回一个未处理的事务。
隔离性: 它是指每个事务在自己的空间发生,和其他发生在系统中的事务隔离,而且事务的结果只在它完全被执行的时候才能看到,如果该事务未提交,则其他会话看不到执行的结果。这样的话即使一个系统中同时发生多个事务,孤立性也可以保证特定的事务在完成之前,其结果是不被公布的。当系统支持多个同时存在的用户和连接时,系统必须遵守孤立性原则,否则在执行过程中可能导致大量数据被破坏,孤立性保证每个事务完整地在其各自的空间内被顺序的执行,保证事务之间不会相互冲突。
持久性: 在MySql中,即使是数据库系统崩溃,一个提交的事务仍然在坚持。当一个事务完成,数据库的日志已经被更新时,持久性即可发挥其特有功效。在MySql中,如果系统崩溃或者数据存储介质被破坏,通过使用日志,系统能够恢复在重启前进行的最后一次成功更新,可以反应系统崩溃时处于执行过程的事务的变化。 MySql的持久性是通过一条记录事务过程中系统变化的二进制事务日志文件来实现的。如果遇到硬件损坏或者系统的异常关机,系统在下一次启动时,通过使用最后的备份和日志就可以恢复丢失数据。

如何使用事务?

1
2
3
4
5
6
7
8
create databases test;
use test;
create table accounts(
id int primary key auto_increment,
name varchar(40),
money float);
insert into accounts(name, money) values('a', 1000);
insert into accounts(name, money) values('b', 1000);

执行效果如下:
2
演示使用事务来实现转账功能:
首先开启一个事务,然后通过update语句将a账户的100元转给b账户,然后提交事务,具体语句如下:

1
2
3
4
start transaction;
update account set money= money- 100 where name= 'a';
update account set money= money+ 100 where name= 'b';
commit;

执行效果如下:
3

Your support will encourage me to continue to create!