事务的概念

事务是逻辑上的一组操作,能够将各SQL语句打包执行,要么全都执行,要么全都不执行

想象我们在操作数据库时,数据库突然挂了,或者多个线程写入数据库时覆盖了彼此的更改……一系列操作都会导致数据库数据的不一致性,基于这些问题,数据库有了事务这一机制。

拿转账举例,A想要向B转账500元,该操作分为两步:

  • A的账户减少500元
  • B的账户增加500元

事务会将这两步打包在一起执行,要么全都执行,要么全都不执行。不会出现A的账户少了500,而B账户没有增加500的情况。

如何使用事务

①开启事务

1
start transaction;

②执行多条SQL语句

1
2
3
4
-- A账户减少500
update accout set money=money-500 where name = 'A';
-- B账户增加500
update accout set money=money+500 where name = 'B';

③回滚或提交:rollback/commit;

1
commit;

说明:rollback即是全部失败,commit即是全部成功。

事务的特性

关系型数据库(例如:MySQLSQL ServerOracle 等)事务都有四大特性:

原子性

原子性:事务为执行的最小单元,不可再划分,要么全都执行,要么全都不执行。

一致性:事务执行前后的数据要保持一致,结果不能出现异常。拿转账举例,转账前后两个账户的总额是不变的。

持久性:事务带来的影响是持久的,不会因为数据库故障而产生任何影响。

隔离性:并发访问数据库时,各事务之间的数据库是独立的,一个用户的事务不会被其他事务所干扰。

只有保证事务的原子性、持久性和隔离性,才能保证事务的一致性,所以说原子性、持久性和隔离性是事务的手段,一致性是目的。

并发事务带来的问题

脏读:一个事务正在访问数据库并对数据进行修改,而该修改并未提交到数据库,另一个进行此时访问数据库读取数据。而这里访问的数据只是一个中间的数据,不一定是最终的结果,这里读到的数据就是一个“脏数据”,基于“脏数据”做出的操作可能是错误的。

不可重复读:在一个事务内多次读取同一数据。在多次读取数据之间,另一个事务访问并修改了该数据,那么再次读取该数据时,发现与之前读取到的数据不一样。在一个事务内两次读取到的数据不一样,称为不可重复读。

幻读:一个事务(T1)读取了几行数据,此时另一个事务(T2)插入了一些数据。事务T1再次读取该数据发现多了一些原本不存在的数据,这就是幻读。幻读是不可重复读的特殊情况,不可重复读强调的是数据的更改,幻读强调的是数据的增加。

事务隔离级别

SQL标准定义了四个隔离级别,隔离级别越高,并行化就越低。

  • read-uncommitted:读取未提交。最低的隔离级别。允许读取未提交的数据,可能导致脏读、不可重复读、幻读。
  • read-committed:读取已提交。不能读取未提交的数据,即事务在修改数据时另一个事务不能执行读操作。可以防止脏读,不能避免不可重复读、幻读。
  • repeatable-read:可重复读。事务在读取数据时,其他事务不能修改正在读取的数据。因此对同一数据的多次修改结果都是一致的,可以防止脏读、不可重复读,不能避免幻读。
  • serializable:串行化。最高的隔离级别。各事务串行执行,相互之间不存在干扰,可以防止脏读、不可重复读和幻读。