事务
概述
事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
在Mysql中只有使用了InnoDB数据库引擎的数据库或表才支持事务。事务处理可以用来维护数据库的完整性,保证成批的sql语句要么全部执行,要么全部不执行。
事务用来管理insert、update、delete语句。
特性
一般来说,事务是必须满足4个条件(ACID):原子性(Atomicity,或称为不可分割性)、一致性(Consistency)、隔离性(Isolation,又称为独立性)、持久性(Durability)。
原子性:一个事务中的所有操作,要么全部执行,要么全部不执行,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
持久性:事务处理结束后,对数据库的修改时永久的,即便系统故障也不会丢失。
隔离性:数据库允许多个并发事务同时对数据进行读写和修改能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交、读提交、可重复复个串行化。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的数据必须完全符合所有的预设规则。比如不能出现转了100元,对方收到了50元的情况。前面提到的原子性、持久性和隔离性都是为了保证数据库状态的一致性。
事务设置
默认情况下,Mysql启动自动提交模式(变量autocommit为ON)。这意味着只要你执行DML操作的语句,Mysql会立即隐式提交事务。
由于变量autocommit分会话系统变量和全局系统变量,所以查询的时候,最好区别是会话系统变量还是全局系统变量。
Mysql事务处理只要有两种方法:
- 用begin,rollback,commit实现:
begin; /start transaction; 开始一个事务
rollback 事务回滚
commit 事务确认
- 直接用 set 来改变Mysql的自动提交模式:
set session/global autocommit = 0; 禁止自动提交
set session/global autocommit = 1; 开启自动提交
查看autocommit模式
show session/global variables like 'autocommit';
并发事务处理带来的问题:
当两个或多个事务选择同一行,然后基于最初选定的值进行更新操作时,由于每个事务都不知道其他事务的存在,则会发生丢失更新的问题,即最后的更新覆盖了前一个程序员所做的更改。
假设有两个事务A和B,同时并发。
(1)脏读:
- 事务B更新年龄18
- 事务A读取数据库信息,年龄是18
- 事务B回滚
这种情况就叫做脏读:读取到其他事务未提交的数据。
(2)不可重复读:在事务A中先后两次读取同一个数据,两次读取的结果不一样,这种现象称为不可重复读。
脏读与不可重复读的区别在于:前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据。
这种情况叫做不可重复读:在同一个事务中两次读取的数据不一致。
(3)幻读:在事务A中按照某个条件先后两次查询数据库,两次查询结果的条数不同,这种现象称为幻读。不可重复读与幻读的区别:前者是数据变了,后者是数据条数变了。
- 事务A读取年龄大于15的数据,发现只有1条
- 事务B插入一条记录,并提交
- 事务A再读取年龄大于15的数据,发现变成了2条
这种就叫做幻读:在同一个事务中两次读取到的数据量不一致。一般幻读出现在范围查询。
事务隔离级别
只有InnoDB支持事务,所以这里说的事务隔离级别是指InnoDB下的事务隔离级别。
查看当前会话隔离级别
show variables like 'tx_isolation'; mysql5
select @@global.transaction_isolation,@@transation_isolation; mysql8
设置当前会话隔离级别
set session transaction isolatioon level read uncommitted
读未提交(read uncommitted):
一个事务可以读取到另一个事务未提交的修改。这会带来脏读,幻读,不可重复读问题。
读已提交(read committed):
一个事务只能读取另一个事务已及提交的修改。避免了脏读,仍然存在不可重复读和幻读的问题。
可重复读(repeatable read MySQL默认隔离级别):
同一个事务中多次读取相同的数据返回的结果是一样的。避免了脏读和不可重复读问题,但幻读依然存在。
串行化(serializable):
事务串行执行,避免了以上所有问题。