一、事务简介
事务是数据库操作的最小工作单元,是一组不可再分割的操作集合,要么全部执行,要么全部失败。
在MySQL中,事务是一组具有原子性的SQL语句,一组 SQL 语句要么全部执行,要么全部不执行。
事务支持是在引擎层实现的,只有使用了 Innodb 数据库引擎的数据库或表才支持事务,MyISAM引擎不支持事务,事务用来管理 insert,update,delete 语句,同时事务是数据库系统区别于其他一切文件系统的重要特性之一。
二、事务四大特征
一般来说,事务是必须满足以下4个特性(ACID):
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
原子性:一个事务(transaction)必须被视为一个不可分割的最小工作单元,整个事务(transaction)中的所有操作,要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。
一致性:数据库总是从一个一致性的状态转换到另外一个一致性的状态,在事务开始之前和事务结束后数据库数据的完整性没有被破坏。(比如:用户A向用户B转账,不可能用户A扣了钱,用户B却没有收到)
隔离性:一个事务对数据库中数据所做的修改,在未提交完成前,对其它事务是不可见的,事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
持久性:一旦事务提交,则对数据的修改就会永久保存到数据库中,即使系统崩溃,修改的数据也不会丢失。
三、事务并发带来的问题
1、脏读
事务A读取了事务B未提交事务的数据。
2、不可重复读
事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
3、幻读
事务A对表中的数据进行了修改,涉及到表中的全部行。同时,事务B也修改这个表中的数据,向表中插入一行新数据。那么,事务A发现表中还有自己没有修改的行,就好象发生了幻觉一样。
四、MySQL的事务
1、MySQL数据库的隔离级别
查看MySQL数据库的隔离级别:
mysql> show variables like 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.01 sec)
MySQL的事务隔离级别:
未提交读(READ UNCOMMITED):即脏读,一个事务还没提交,它做的变更就能被其他事务看到。
已提交读(READ COMMITED):一个事务提交之后,它做的变更才会被其他事务看到。
可重复读(REPEATABLE READ):一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。MySQL默认隔离级别是可重复读,InnoDB存储引擎在REPEATABLE READ事务隔离级别下,使用Next-KeyLock锁的算法,因此避免幻读的产生。
可串行化(SERIALIZABLE):完全串行化读,在读取的每一行数据都加锁,每次都会锁表,读写互相阻塞。对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
innodb引擎对隔离级别支持
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交(READ UNCOMMITED) | √ | √ | √ |
读已提交(READ COMMITED) | × | √ | √ |
可重复读(REPEATABLE READ) | × | × | × (InnoDB不存在幻读) |
串行化(SERIALIZABLE) | × | × | × |
2、事务的执行过程
begin(或start transaction)开始事务。
rollback回滚事务/commit提交事务。
3、事务的自动提交
mysql的autocommit代表事务是否自动提交。mysql默认为自动提交,即当begin开始一个事务后,关闭mysql会话窗口,没有执行rollback或者commit操作,sql语句会自动提交。当autocommit关闭后(autocommit=0),需要执行commit才会将事务提交,关闭mysql会话后,则不会提交事务。
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.04 sec)
以上命令来查看当前事务提交状态,value列的on表示当前为自动提交状态。
执行set autocommit=0; 关闭自动提交事务。(autocommit : 0 为关闭,1为开启)
mysql> set autocommit=0;