一、事务的简介
1. 事务的概念
事务(Transaction)是一个操作序列,该序列中的多个操作要么都做,要么都不做 是MySQL5.5之后的存储引擎所支持事务,就是把一堆事情绑在一起做,都成功了才算完成,否则就恢复之前的样子 举例:银行ATM取钱,扣款成功后突然大停电,吐钱的操作还没做,这时候ATM机就要恢复到没取钱时候的状态,否则钱扣了还没拿到手,多冤枉
事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所做的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。 事务的结束有两种,当事务中的所有步骤全部成功执行时,事务提交。如果其中一个步骤失败,将发生回滚操作,撤消之前到事务开始时的所有操作。
2. 事务的特点( 简称 ACID)
a. 原子性(atomicity)
原子是自然界中最小的颗粒,具有不可再分的特点,事务中的所有操作可以看作是一个原子(事务是数据库的逻辑工作单位),要么全部执行,要么全不执行.
b. 一致性(consistency)
事务执行的结果必须要保证数据库中数据的一致性事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态 。
c.隔离性(isolation)
隔离性指各个事务的操作是互不干扰的,即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
d.持久性(durability)
持久性也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响.
二、事务的控制
1.创建一个库 test1
2.创建一张表account(id账号主键唯一,username账号名,balance金额)
3.插入数据
--创建表account
create table account(
id int(8) primary key auto_increment,
username varchar(30),
balance double
);
--插入数据
insert into account(username,balance) values('张三',2000),('李四',2000)
--查询数据
select * from account;
1.开启事务
语法:start | begin transaction开启一个新的事务
例如:开启新事务,完成张三给李四转账200
--开启新事务,完成张三给李四转账200
start transaction;
update account set balance=balance-200 where username='张三';
update account set balance=balance+200 where username='李四';
注意:使用start transaction 开启一个新事务后,该事务不会自动提交,必须手动提交。
2.提交事务
语法:commit
start transaction;
update account set balance=balance-200 where username='张三';
update account set balance=balance+200 where username='李四';
commit;
3.回滚事务
语法:rollback
注意:开启的事务,未提交时候可以回滚。
start transaction;
update account set balance=balance-200 where username='张三';
update account set balance=balance+200 where username='李四';
rollback;
三、事务的隔离级别
事务的隔离级别用于决定如何控制并发用户读写数据的操作,事务的隔离级别由低到高分为:
1. read uncommitted
指:读取未提交的数据内容
--张三开启事务,进行转账操作 但不提交事务
start transaction;
update account set balance=balance-200 where username='张三';
update account set balance=balance+200 where username='李四';
--设置事务隔离级别为read uncommitted
set session transaction isolation level read uncommitted;
--查看事务隔离级别
select @@transaction_isolation
--开启事务,查询表中的数据,(隔离级别为read uncommitted)可以查询到未提交的数据
start transaction;
select * from account;
张三开启事务进行转账,但未提交事务,李四设置了隔离级别是read uncommitted,开启事务查询数据时就可以看到张三修改后的数据,如果张三现在做回滚操作,则李四看到的数据就是脏数据。
2. read committed
指:读取提交的数据,该隔离级别下,所有事务只能看到其他事务已经提交的数据,该隔离级别解决了脏读的问题
--设置李四窗口的隔离级别为 read committed
set session transaction isolation level read committed;
--查看设置是否成功
select @@transaction_isolation
--开启事务读取数据
start transaction;
select * from account;
--张三开启事务进行转账,不提交事务
start transaction;
update account set balance=balance-200 where username='张三';
update account set balance=balance+200 where username='李四';
--提交事务
commit;
李四设置了隔离级别是read committed,开启事务查询数据,张三开始事务进行转账,但不提交事务,李四查询数据时候没有看到转账的数据还是原来的数据,当张三提交了事务,李四查询数据时候可以看到提交后的数据,这样解决了脏读的问题,但是李四前后两次读取数据的结果不一致,则read committed不能解决重复读的问题。
3. repeatable read
指:(可重复读)是MySQL默认的隔离级别
--设置李四窗口的隔离级别为 repeatable read
set session transaction isolation level repeatable read;
--查看设置是否成功
select @@transaction_isolation
--开启事务读取数据
start transaction;
select * from account;
--张三开启事务进行转账,不提交事务
start transaction;
update account set balance=balance-200 where username='张三';
update account set balance=balance+200 where username='李四';
--提交事务
commit;
李四设置隔离级别 repeatable read,开启事务查询数据, 张三开启事务进行转账,但不提交数据,李四查询数据,则看到还是原来的数据 张三提交事务,李四查询数据,看到的数据还是原来的数据,查询的数据前后都是相同的数据 则repeatable read解决了不可重复读取的问题
幻读幻读是指当事务不是独立执行时发生的一种现象。
SQL标准这么定义幻读,在两个连续的查找之间一个并发的修改事务修改了查询的数据集,导致这两个查询返回了不同的结果。
--设置李四窗口的隔离级别为 repeatable read
set session transaction isolation level repeatable read;
--查看设置是否成功
select @@transaction_isolation
--开启事务读取数据
start transaction;
select * from account;
--张三开启事务,插入数据,并提交
start transaction;
insert into account(username,balance) values('王五',2000);
commit;
测试:李四设置隔离级别 repeatable read,但是没有产生幻读问题,因为:MySQL中InnoDB存储引擎使用(MVCC机制)解决了repeatable read 下的幻读问题。Multi-Version Concurrency Control 多版本并发控制,MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
事务内存(英语:Transactional memory)是一种并行程序设计的方式,其来自于数据库管理系统(DBMS)中的事务(Transaction)概念。事务内存目前有两种实现方式,基于软件的软件事务内存(STM)和基于硬件的HTM(Hardware Transactional Memory)。
--设置李四窗口的隔离级别为 read committed
set session transaction isolation level read committed;
--查看是否设置隔离级别成功
select @@transaction_isolation
--开启事务读取数据
start transaction;
select * from account;
--张三开启事务,插入数据,并提交
start transaction;
insert into account(username,balance) values('赵六',2000);
--提交事务
commit;
设置隔离级别为read committed,开启事务查询数据,另一个事务进行插入数据,并提交,在查询事务中再次查询,结果可以查询到刚刚插入的数据,则产生幻读
4.serializable
(可串行化)该隔离级别是最高的,同时花费也是最高的,性能最低,一般很少用。因为在该隔离级别下,事务按着顺序执行。
--设置李四窗口的隔离级别为 serializable
set session transaction isolation level serializable;
--查看是否设置隔离级别成功
select @@transaction_isolation
--开启事务读取数据
start transaction;
select * from account;
--张三开启事务,插入数据,并提交(查看是否让插入)
start transaction;
insert into account(username,balance) values('张无忌',2000);
--提交事务
commit;