1、什么是事务
事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成,事务是不可以再分的最小的数据库工作单元,它包含了一个或者多个 DML 语句,比如 insert、update、delete。
InnoDB 存储引擎是支持事务的,这也是它成为默认的存储引擎的一个重要原因。
最常见的事务操作就是金融系统的银行转账场景,简单的说 A 账户转出多少金额给 B 账户,那么 B 账户必须完成对应金额的增加,这个转账业务才算成功,否则就出大问题了。
再比如电商系统的下订单场景,订单表和库存表一定是要在一个事务里完成的。
事务里的操作,要么同时成功,要么同时失败,这样才能保证事务操作的一致性。
2、事务的四大特性
事务的四大特性:ACID。
1、原子性(Atomicity)
原子性,又叫不可分割性,它是指一个事务(transaction)中的所有操作,要么全部成功,要么全部失败。如果事务在执行过程中发生错误,就会被回滚(rollback)到事务执行之前的状态,也就是说要返回原样,就像这个事务从来没有执行过一样。
原子性的回滚操作在 InnoDB 里面是通过 undolog 来实现的,它记录了数据修改之前的值(逻辑日志),一旦发生异常,就可以用 undo log 来实现回滚操作。
2、一致性(Consistent)
一致性,指的是在事务执行前后,数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。比如主键必须是唯一的,字段长度符合要求等,也不会因为系统出现异常等原因导致数据前后的状态不一致。
除了数据库自身的完整性约束,我们在写代码的时候,还要满足用户自定义的完整性。比如:A 账户要给 B 账户转账 10000 元,如果 A 账户余额减少 10000 元,B 账户余额只增加了 1000 元,这个时候两个 sql 操作都可以成功,因为它是满足原子性的,但是明显存在业务问题;假设 A 账户里没有 10000 元,那么也是不能够执行转账操作的,一般用户自定义的完整性需要在代码中做好判断和控制。
3、隔离性(Isolation)
隔离性可以防止多个事务并发的读写操作时,由于交叉执行而导致数据的不一致。因为数据库允许多个并发事务同时去读写或者修改数据库的同一张表或者同一行数据,如果不加控制,数据一定会不一致。隔离性就是指多个并发事务对同一张表或者同一行数据的读写操作,应该是互相不干扰的。主要是指一个事务要操作的数据在提交之前,对其他事务应该是不可见的,从而可以保证业务数据的一致性。
数据库的隔离性是通过事务的隔离级别来实现的。
4、持久性(Durable)
持久性是指事务处理(对数据库的任意的增删改操作)结束后,对数据的修改就是永久的,即便数据库宕机也不会丢失(数据库的磁盘文件损坏除外)。
数据库宕机后的恢复是通过 redolog 来实现的数据持久性恢复,数据库在操作数据的时候,会先写到内存的 buffer pool 里面,同时记录 redo log。如果在写到磁盘之前出现异常,那么重启后就可以读取 redo log 的内容,然后再写入到磁盘,从而保证数据的持久性。
其实事务的原子性、隔离性、持久性,最后都是为了实现事务的最终一致性。
3、MySQL 如何开启事务
1、自动开启事务,自动提交或者回滚事务
InnoDB 有一个 autocommit 的参数(分成两个级别, session 级别和 global 级别)。
show variables like 'autocommit';
它的默认值是ON,如果 autocommit 值是 true/on 的话,我们在操作数据的时候,会自动开启一个事务,和自动提交事务;如果把 autocommit 设置成 false/off,那么数据库的事务就需要我们手动地去开启和手动地去结束。
2、手动开启事务,手动提交或者回滚
手动开启事务可以用 begin,也可以用 start transaction;结束一个事务也有两种方式,可以用 commit 提交一个事务,也可以用 rollback 回滚事务。