MySQL事务
什么是事务
事务就是一组逻辑操作的集合。
- 事务:一条或者多条对数据库操作的SQL语句所组成的一个不可分割的单元
- 事务的所有SQL语句全部执行成功,才能提交(commit)事务,把结果写回磁盘上。
- 事务执行过程中,有的SQL出现错误,那么事务必须要回滚(rollback)到最初的状态
怎么实现事务
实现事务就是要保证可靠性和并发隔离,或者说,能够满足ACID特性的机制。而这些主要是靠日志恢复和并发控制实现的
- 日志恢复:数据库里有两个日志,一个事redo log,一个事undo log。redo log记录的是已经成功提交的事务操作信息,用来恢复数据,保证事务的持久性。undo log记录的是事务修改之前的数据信息,用来回滚数据,保证事务的原子性。
- 并发控制:并发控制主要靠读写锁和MVCC(多版本控制)来实现。读写锁包括共享锁和排它锁,保证事务的隔离性。MVCC通过为数据添加时间戳来实现
事务的ACID特性
- 原子性(Atomic):事务是一个不可分割的工作单位,这组操作要么全部发生,要么全部不发生
- 一致性(Consistency):在事务开始以前,数据库中的数据有个一致的状态。在事务完成以后,数据库中的事务也应该保持这种一致性。即事务应该将数据从一个一致性状态移动到另一个一致性状态
- 隔离性(Isolation):数据库中的事务不会受另一个并发执行的事务的影响
- 持久性(Durability):事务对数据库的改变是永久的。事务完成(commit)以后,DBMS保证它对数据库中的数据的修改是永久性的,即使数据库因为故障出错,也应该能够恢复数据!
事务并发存在的问题
- 脏读(Dirty Read):脏读是指一个事务在处理过程中读取了另一个还没提交的事务的数据。
- 不可重复读(NonRepeatable Read):不可重复读是对于数据库中的某一个字段,一个事务多次查询却返回了不同的值,这是由于在查询的间隔中,该字段被另一个事务修改并提交了。
- 幻读(Phantom Read ):事务多次读取同一个范围的时候,查询结果的记录数不一样,这是由于在查询的间隔中,另一个事务新增或删除了数据。
事务的隔离级别
为了保证数据库事务一致性,解决脏读,不可重复读和幻读的问题,数据库的隔离级别一共有四种隔离级别:
- 读未提交:最低级别的隔离,不能解决以上问题
- 读已提交:只允许读已提交的数据,可以避免脏读的发生
- 可重复读:确保事务可以多次从一个字段中读取相同的值,在该事务执行期间,禁止其他事务对此字段的更新,可以避免脏读和不可重复读。 通过锁行来实现
- 串行化:最严格的事务隔离机制,要求所有事务被串行执行,可以避免以上所有问题。 通过锁表来实现
隔离级别 | 脏读 | 不可重复度 | 幻读 |
---|
读未提交 | 未解决 | 未解决 | 未解决 | 读已提交 | 解决 | 未 | 未 | 可重复读 | 解决 | 解决 | 未 | 串行化 | 解决 | 解决 | 解决 |
Oracle的默认隔离级别是读已提交,实现了四种隔离级别中的读已提交和串行化隔离级别
MySQL的默认隔离级别是可重复读,并且实现了所有四种隔离级别
MySQL事务处理的命令
# 查看MySQL是否自动提交事务
select @@autocommit; # 0表示手动提交事务,1表示自动提交事务
# 设置事务提交方式为手动提交方式
set autocommit=0;
# 开启一个事务
BEGIN
#提交一个事务
COMMIT
# 回滚一个事务到初始的位置
ROLLBACK
# 设置一个名字为point1的保存点
SAVEPOINT point1;
# 事务回滚到保存点point1,而不是回滚到初始状态
ROLLBACK TO point1;
# 设置事务的隔离级别
SET TX_ISOLATION='REPEATABLE-READ';
# 查询事务的隔离级别
SELECT @@ TX_ISOLATION;
|