11、事务的基础概念
事务的基础概念
事务的认识
事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。当在一个事务中执行多个操作时,要么所有的事务都被提交( commit ),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改 ,整个事务回滚( rollback )到最初状态。
事务的ACID特性
- 原子性(atomicity):由undo日志来保证
原子性是指事务是一个不可分割的工作单位,要么全部提交,要么全部失败回滚。
- 一致性(consistency):由原子性、隔离性、持久性来保证
一致性是指事务执行前后,数据从一个合法性状态变换到另外一个合法性状态 。
- 隔离型(isolation):由MVCC或者锁来保证
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability):由redo日志来保证
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的数据库故障不应该对其有任何影响。
当我们通过事务对数据进行修改的时候,首先会将数据库的变化信息记录到redo重做日志中,然后再对数据库中对应的行进行修改。当数据库系统崩溃,数据库重启后也能找到没有更新到数据库系统中的重做日志,重新执行,从而使事务具有持久性。
事务的状态
一个事务执行的不同阶段:
- 活动的(active)
事务对应的数据库操作正在执行过程中时,我们就说该事务处在活动的状态。 - 部分提交的(partially committed)
当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并没有刷新到磁盘时,我们就说该事务处在部分提交的状态。 - 失败的(failed)
当事务处在活动的或者部分提交的状态时,可能遇到了某些错误(数据库自身的错误、操作系统错误或者直接断电等)而无法继续执行,或者人为的停止当前事务的执行,我们就说该事务处在失败的状态。 - 中止的(aborted)
如果事务执行了一部分而变为失败的状态,那么就需要把已经修改的事务中的操作还原到事务执行前的状态。 - 提交的(committed)
当一个处在部分提交的状态的事务将修改过的数据都 同步到磁盘 上之后,我们就可以说该事务处在了提交的状态。
使用事务
显示开启事务
1、使用START TRANSACTION或者BEGIN
2、提交事务或回滚事务(对于DML语句必须执行该操作)
隐式事务
MySQL中有一个系统变量autocommit,当该值为ON时,每执行一条语句都会自动提交事务。
隐式提交数据的情况(会提交上一个事务,自己也会提交)
- 数据定义语言(Data definition language,缩写为:DDL)
- 隐式使用或修改mysql数据库中的表
- 事务控制或关于锁定的语句
当我们在一个事务还没提交或者回滚时就又使用 START TRANSACTION 或者 BEGIN 语句开启了另一个事务时,会隐式的提交上一个事务。
当前的autocommit系统变量的值为OFF,我们手动把它调为ON时,也会隐式的提交前边语句所属的事务。
使用LOCK TABLES 、UNLOCK TABLES等关于锁定的语句也会隐式的提交前边语句所属的事务。
事务的隔离级别
数据并发问题
当多个事务访问相同的数据时,如果未采用隔离手段,则会出现以下问题:
脏写( Dirty Write )
事务Session A修改了另一个未提交事务Session B修改过的数据,那就意味着发生了脏写
脏读( Dirty Read )
事务Session A读取了另一个未提交事务Session B更新过的字段。之后若Session B回滚,Session A读取的内容就是临时且无效的。
不可重复读( Non-Repeatable Read )
事务Session A从一个表中读取了一个字段但未提交事务,然后Session B更新了该字段并且提交了事务。之后Session A再次读取同一个字段,值就改变了。那就意味着发生了不可重复读。
幻读( Phantom )
事务Session A从一个表中读取了一个字段的数据(结果为NULL值)但未提交事务, 然后Session B在该字段插入了一行数据并且提交了事务。之后, 如果Session A再次读取同一字段,发现有数据了。那就意味着发生了幻读。
SQL中的四种隔离级别
SQL标准中设立了4个隔离级别,隔离级别越高,并发性就越低,发生的并发问题就越少。
如何设置事务的隔离级别
关于设置时使用GLOBAL或SESSION的影响: