15.1 事务概述
当多个用户访问同一份数据,一个用户在更改数据的过程中可能有其他用户同时发起更改请求,为保证数据库记录的更新从一个一致性状态变为另一个一致性状态,使用事务处理是非常必要的。
事务有以下4个特性:
- 原子性:事务中所有的操作都视为一个原子单元,即对于事务所进行的数据修改等操作只能是完全提交或者完全回滚。
- 一致性:事务在完成时,必须使所有数据从一个一致性状态变为另一个一致性状态,所有的变更都必须应用于事务的修改,以确保数据的完整性。
- 隔离性:一个事务的操作语句所做的修改必须与其他事物的操作语句所做的修改相隔离,当前事务不会查看由另一个并发事务正在修改的数据。这种机制通过锁机制实现。
- 持久性:事务完成之后,所做的修改对数据的影响是永久的,即使系统重启或者出现系统故障数据仍可以恢复。
15.2 MySQL事务控制语句
START TRANSACTION | BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT = {0 | 1}
15.3 MySQL事务隔离级别
SQL定义了4种隔离级别,指定了事务中哪些数据改变其他事务可见,哪些数据改变其他事务不可见。低级别的隔离级别可以支持更高的并发处理,同时占用的系统资源更少。
SET [SESSION | GLOBAL] TRANSACTION
ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
1. READ UNCOMMITTED (读取未提交内容)
所有事务都可以看到其他未提交事务的执行结果。因为其性能也不比其他级别高很多,因此此隔离级别实际应用中一般很少使用,读取未提交的数据称为脏读(Dirty Read)。
2. READ COMMITTED (读取提交内容)
这是大多数数据库系统的默认隔离级别,但不是MySQL默认的隔离级别。这种隔离级别支持所谓的不可重复读(Nonrepeatable Read)。
3. REPEATABLE READ (可重读)
这是MySQL的默认事务隔离级别,能确保同一个事务的多个实例在并发读取数据时,会看到同样的数据行,理论上会导致另一问题:幻读(Phantom Read)。InnoDB存储引擎通过多版本并发控制(MVCC)机制解决了该问题。
4. SERIALIZABLE (可串行化)
这是最高的隔离级别,通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,是在每个读的数据行加上共享锁实现。在这个级别,可能会导致大量的超时现象和锁竞争,一般不推荐使用。
15.4 InnoDB锁机制
15.4.1 锁的种类
1. 共享锁 S
锁粒度是行或元组(多行)。一个事务获取了共享锁之后,可以对锁定范围内的数据执行读操作。
2. 排它锁 X
锁粒度是行或元组(多行)。一个事务获取了排他锁之后,可以对锁定范围内的数据执行写操作。
3. 意向锁 IS IX
意向锁是一种表锁,锁定的粒度是整张表,分为意向共享锁(IS)和意向排它锁(IX)两类。
意向锁表示一个事务有意对数据上共享锁或排它锁。
参数 | X | S | IX | IS |
X | N | N | N | N |
S | N | Y | N | Y |
IX | N | N | Y | Y |
IS | N | Y | Y | Y |
Y表示兼容,N表示互斥。
15.4.2 锁的粒度
表锁:管理锁的开销最小,同时允许的并发量也是最小。MyISAM存储引擎使用该锁机制。当要写入数据时,把整个表记录被锁,此时其他读、写动作一律等待。同时一些特定的动作,如ALTER TABLE执行时使用表锁。
行锁:可以支持最大的并发。InnoDB存储引擎使用该锁机制。如果要支持并发读/写,建议采用行级锁,可以获得更多的更新性能。当开启一个事务时,InnoDB存储引擎会在更新的记录上加上一个行级锁,此时其他事务不可以更新被锁定的记录。