mysql之事务的理解

事务:transaction,事务是一组业务逻辑,在整个业务逻辑的执行过程中要么全部成功,要么全部失败,整个业务全部执行完成结束后事务才算结束

事务安全:一种保护连续操作同时满足(实现)的一种机制

事务安全的意义:保证数据操作的完整性

事务操作

事务分为两种:自动事务(默认的),手动事务

创建一张表
create table my_account(

id int primary key auto_increment,
number varchar(20) not null unique comment ‘卡号’,
name varchar(10),
money decimal(10,2) default 0 comment ‘账户余额’

)charset utf8;

插入数据:
mysql之事务的理解
此时,张三需要给李四转1000块钱,需要两步,第一步张三账户余额减少1000块,第二步李四账户余额增加一千块
mysql之事务的理解
张三减少余额后停电了,或者因为其他一些原因系统宕机了,此时张三减少了余额,但是李四的余额没有增加

手动事务操作流程

  1. 开启事务:告诉系统以下所有操作不直接写到数据表,而是先存放到事务日志 start transaction;
    mysql之事务的理解

  2. 进行事务操作:
    a)李四账户余额减少1000
    mysql之事务的理解
    在打开以个mysql操作界面查询my_account表
    mysql之事务的理解
    李四的账户余额依然是两千
    b)张三用户余额增加1000
    mysql之事务的理解
    但是用另外的一个mysql操作界面查看依然没有变化
    mysql之事务的理解

  3. 关闭事务:选择性的将日志文件中操作的结果保存到数据表或者说直接清空日志(原来的操作全部清空)
    a)提交事务,同步数据表:commit;
    mysql之事务的理解b)回滚事务,直接清空日志表:rollback;
    已经提交的事务rollback无效

使用事务必须使用InnoDB存储引擎,因为myisam存储引擎不支持事务

事务原理

事务操作原理: 事务开启之后,所有的操作都会临时保存到事务日志,临时日志只有在得到commit命令才会同步到数据表,其他任何情况都会清空(rollback, 断电, 断开连接等)

回滚点

回滚点:在某个成功的操作完成之后,后续的操作可能成功也可能失败,但不管成功还是失败,前面操作都已经成功,,可以在当前成功的位置,设置一个点,可以供后续失败操作返回到该位置,而不是返回所有操作,这个点称之为回滚点。

设置回滚点语法:savepoint 回滚点名称;

回到回滚点语法:rollback to 回滚点名称;
mysql之事务的理解
开启事务

给李四发工资10000
mysql之事务的理解
然后在这里设置一个回滚点
mysql之事务的理解
银行需要扣李四的税,结果发现扣错了,这个时候需要回滚到刚才成功发完工资的时候的操作
mysql之事务的理解
回滚到成功发工资的操作
rollback to sp1;
mysql之事务的理解
再次进行给李四扣税
mysql之事务的理解
提交事务
mysql之事务的理解

自动事务

在mysql中默认的都是使用自动提交事务,用户操作完会立即同步到数据表中

自动事务: 系统通过autocommit变量进行控制
show variables like ‘autocommit’;
mysql之事务的理解
关闭自动提交:set autocommit = off; 或者 set autocommit = 0;
mysql之事务的理解
再次进行写操作,这次不用开启事务
mysql之事务的理解
注意:通常我们都会使用自动提交事务(mysql默认是自动提交事务的)
mysql之事务的理解

事务特性

事务的四大特性: ACID
A:原子性(Atomicity),事务的整个操作是一个整体,不可分割,要么全部成功,要么全部失败;
C:一致性(Consistency),事务操作的前后,数据表中的数据没有变化;
I:隔离性(Isolation),事务操作是相互隔离不受影响的;
mysql之事务的理解
D:Durability,持久性,数据一旦提交,不可改变,永久的改变数据表数据

锁机制:innodb默认是行锁,但是如果事务操作过程中没有使用到索引,那么系统会自动检索全表数据,自动升级为表锁
行锁:只有当前行被锁住,别的用户不能操作
表锁:整张表被锁住,别的用户不能操作
mysql之事务的理解

事务的隔离级别

四种隔离级别

Read Uncommitted(读未提交)
在该隔离级别,所有的事务都可以看到其他事务未提交的执行结果。本隔离级别很少用于实际应用,因为它的性能不比其他级别好多少。读取未提交的是数据,也被称之为脏读(Dirty Read)

Read Committed(读已提交)
这是大多数数据库默认的隔离级别(但不是mysql的默认隔离级别)。它满足了隔离的简单定义:一个事务只能看见已经提交的事务所做的改变。这种隔离级别也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理期间可能会有新的commit,所以同一select可能返回不同结果

Repeatable Read(可重复读)
这是mysql默认的事务隔离级别,它确保同一事务在多个实例并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个数据又在该范围内插入了新行,当用户再次读取该范围数据时,会发现新的‘幻影’行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

Serializable(可串行读)
这是最高的隔离级别,它是通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别可能存在大量的超时现象和锁竞争现象。

在mysql中实现了这四种隔离级别,分别有可能产生问题,如下所示:
mysql之事务的理解

这四种隔离级别采用不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题,如:

脏读(Dirty Read):某个事务已经更新了一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个事务Rollback了操作,则后一个事务所读取的数据就是不正确的

不可重复读(Nonrepeatable Read):在一个事务的两次查询之中数据不一致,这可能是两个查询中间插入了一个事务更新了原有的数据

幻读(Phantom Read):在一个事务中两次查询的数据不一致,例如有一个事务查询了几列数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的

不可重复读和幻读的区别:
不可重复读:A事务在执行过程中,B事务对数据进行了修改或删除,导致A事务两次读取的数据不一致;重点在于updata和delete
幻读:A事务在执行过程中,B事务新增了许多A事务要查询的数据,导致A事务两次读取的数据不一致;重点在于insert