概述
事物(Transaction)是数据库区别于文件系统的重要特征之一。在MySQL数据库中,有些存储引擎是不支持事物的,而主流的InnoDB存储引擎是支持事物的。事物的主要目的,事物会把数据库从一种一致状态转换为另一种一致状态;即要么所有的修改都已经保存,要么所有的修改都不保存。
事物的特性ACID
- A(Atomicity)原子性,一个事物里面所有包含的SQL语句是一个执行整体,不可分割,要么都做,要么都不做。
- C(Consistency)一致性,事物将数据库从一种状态转变为下一种一致的状态,在事物开始之前和事物结束之后,数据库的完整性约束没有被破坏。
- I(Isolation)隔离性,也成并发控制,每个读写事物的对象对其他事物的操作对象能相互分离,即该事物提交前对其他事物都不可见。
- D(Durability)持久性,事物一旦提交,其结果就是永久性的。即使发生宕机等故障,数据库也能将数据恢复。
事物分类
- 1、扁平事物(Flat Transaction),是事物类型中最简单的一种,由BEGIN WORK开始,由COMMIT WORK或ROLLBACK WORK结束,期间的操作都是原子的。
- 2、带有保存点的扁平事物(Flat Transactions with Savepoint),保存点用来通知系统应该记住事物当前的状态,以便发生错误时,事物能回到保存点当时的状态。
- 3、链事物(Chained Transaction),可视为保存点模式的一种变种。带有保存点的扁平事物,当发生系统崩溃时,所有的保存点都将消失;链事物在提交一个事物时,释放不需要的数据对象,将必要的处理上下文隐式地传给下一个要开始的事物。
- 4、箱套事物(Nested Transaction),是一个层次结构框架,由一个顶层事物控制各个层次的事物。
- 5、分布式事物(Distributed Transactions),通常是在一个分布式环境下运行的扁平事物,因此需要根据数据所在位置访问网络中的不同节点。
数据异常
- 脏读,读到了未提交的事物数据;
- 不可重复读,第一次查询和第二次查询到的数据不一样;
- 幻读,在范围读取时,原来没有,现在有了,例如记录条数;
事物的隔离级别
- 读未提交(READ UNCOMMITTED),允许脏读,但不允许更新丢失(排它锁);一个事物已经开始写数据,另一个事物不允许同时进行写操作,但允许读操作;
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
- 读提交(READ COMMITTED),Oracle默认的隔离级别,允许不可重复读,但不允许脏读。读数据的事物允许其他事物访问这行数据,写数据库的事物在未提交前禁止其它事物访问这行数据;
SET GLOBAL TEANSACTION ISOLATION LEVEL READ COMMTTED;
- 可重复读(REPEATABLE READ),MySQL默认的隔离级别,禁止不可重复读和脏读,但有可能会出现幻读,InnoDB中此隔离级别不允许幻读,共享锁和排他写锁。读事物禁止写事物,写事物禁止其他事物。
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ
- 序列化(SERIALIZABLE),读也加锁,要求事物串行化执行。在此隔离级别中,Innodb会对每一个select语句后自动加上lock in share mode。
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(READ UNCOMMITTED) | √ | √ | √ |
读已提交(READ COMMITTED) | × | √ | √ |
可重复读(REPEATABLE READ) | × | × | √ |
串行化(SERIALIZABLE) | × | × | × |
锁的类型
InnoDB存储引擎实现了两种锁:
1、共享锁(Shared Lock)也叫读锁,多个事物可以同时为一个对象加共享锁。
2、排它锁(Write Lock)也叫写锁,如果一个事物对象加了排它锁,其他事物就不能再给它加任何锁了。
排他锁 | 共享锁 | |
---|---|---|
排它锁 | 不兼容 | 不兼容 |
共享锁 | 不兼容 | 兼容 |
事物的错误使用习惯
循环中提交事物
大多数开发人员都知道不应该在循环中进行事物提交,但是有人可能不知道InnoDB存储引擎自动提交的情况。正确的做法应该是在一个循环开始前开启事物,在循环结束后,执行事物提交或者回滚。
使用自动提交
就像上面讲到的,InnoDB存储引擎会进行隐式的自动提交,即使是一条普通的SQL语句,InnoDB存储引擎也会为它加上提交语句。我们需要做的应该是关闭自动提交,尽可能的把事物管理交给开发人员。
SET autocommit = 0;
长事物
顾名思义,就是执行时间较长的事物。对于一些超级大的数据处理,处理时间可能长达1个小时,甚至更久;而执行事物回滚可能会比执行事物花费更多的时间。因此,对于长事物的问题,有时可以通过转化为小批量的事物来进行处理,当事物发生错误时,只需要回滚一部分数据,然后接着上次已完成的事物继续进行。
网友评论