MySQL数据库:事务
事务的概念
事务是逻辑上的一组操作,能够将各SQL语句打包执行,要么全都执行,要么全都不执行。
想象我们在操作数据库时,数据库突然挂了,或者多个线程写入数据库时覆盖了彼此的更改……一系列操作都会导致数据库数据的不一致性,基于这些问题,数据库有了事务这一机制。
拿转账举例,A想要向B转账500元,该操作分为两步:
- A的账户减少500元
- B的账户增加500元
事务会将这两步打包在一起执行,要么全都执行,要么全都不执行。不会出现A的账户少了500,而B账户没有增加500的情况。
如何使用事务
①开启事务
1 | start transaction; |
②执行多条SQL语句
1 | -- A账户减少500 |
③回滚或提交:rollback/commit;
1 | commit; |
说明:rollback即是全部失败,commit即是全部成功。
事务的特性
关系型数据库(例如:MySQL
、SQL Server
、Oracle
等)事务都有四大特性:
原子性
原子性:事务为执行的最小单元,不可再划分,要么全都执行,要么全都不执行。
一致性:事务执行前后的数据要保持一致,结果不能出现异常。拿转账举例,转账前后两个账户的总额是不变的。
持久性:事务带来的影响是持久的,不会因为数据库故障而产生任何影响。
隔离性:并发访问数据库时,各事务之间的数据库是独立的,一个用户的事务不会被其他事务所干扰。
只有保证事务的原子性、持久性和隔离性,才能保证事务的一致性,所以说原子性、持久性和隔离性是事务的手段,一致性是目的。
并发事务带来的问题
脏读:一个事务正在访问数据库并对数据进行修改,而该修改并未提交到数据库,另一个进行此时访问数据库读取数据。而这里访问的数据只是一个中间的数据,不一定是最终的结果,这里读到的数据就是一个“脏数据”,基于“脏数据”做出的操作可能是错误的。
不可重复读:在一个事务内多次读取同一数据。在多次读取数据之间,另一个事务访问并修改了该数据,那么再次读取该数据时,发现与之前读取到的数据不一样。在一个事务内两次读取到的数据不一样,称为不可重复读。
幻读:一个事务(T1)读取了几行数据,此时另一个事务(T2)插入了一些数据。事务T1再次读取该数据发现多了一些原本不存在的数据,这就是幻读。幻读是不可重复读的特殊情况,不可重复读强调的是数据的更改,幻读强调的是数据的增加。
事务隔离级别
SQL标准定义了四个隔离级别,隔离级别越高,并行化就越低。
- read-uncommitted:读取未提交。最低的隔离级别。允许读取未提交的数据,可能导致脏读、不可重复读、幻读。
- read-committed:读取已提交。不能读取未提交的数据,即事务在修改数据时另一个事务不能执行读操作。可以防止脏读,不能避免不可重复读、幻读。
- repeatable-read:可重复读。事务在读取数据时,其他事务不能修改正在读取的数据。因此对同一数据的多次修改结果都是一致的,可以防止脏读、不可重复读,不能避免幻读。
- serializable:串行化。最高的隔离级别。各事务串行执行,相互之间不存在干扰,可以防止脏读、不可重复读和幻读。