MYSQL数据库事务与事务的隔离级别

事务

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。

转账案例

MYSQL数据库事务与事务的隔离级别_第1张图片
张三向李四转账1000。
第一步:查询张三账户余额。
第二步:张三账户减少1000元。
第三步:李四账户增加1000元。

一步到第三步是一个事务,如果没有事务管理,在第二步执行结束之后出现了异常,导致程序终止退出了,就出现问题了。
张三账户余额减少了1000,但是李四账户并没增加1000。钱去哪儿了?
这就体现出事务的重要性了。

mysql中的事务

MySQL中的事务提交方式默认为自动提交,为了事务的灵活性,我们需要就将MySQL的事务设置为手动提交

方式一

#查询事务提交方式(默认为1,自动提交;0为手动提交
SELECT @@autocommit;
SET @@autocommit = 0;
#方式一
#转账操作(张三给李四转账1000)
#1.查询张三余额
SELECT * FROM account WHERE NAME = '张三';

#2.张三余额减少1000
UPDATE account SET money = money - 1000 WHERE NAME = '张三';

#模拟异常
#程序抛出异常...

#3.李四余额增加1000
UPDATE account SET money = money + 1000 WHERE NAME = '李四';

#提交事务
COMMIT;
#回滚事务
ROLLBACK;

首先执行第1、2、3条sql语句,如果程序没有出现异常,再执行commit命令;如果命令执行期间出现了异常,则执行RollBack命令将数据回滚。

方式二

#方式二

#开启事务 start transaction 或 begin;
START TRANSACTION;

#转账操作(张三给李四转账1000)
#1.查询张三余额
SELECT * FROM account WHERE NAME = '张三';

#2.张三余额减少1000
UPDATE account SET money = money - 1000 WHERE NAME = '张三';

#模拟异常
#程序抛出异常...

#3.李四余额增加1000
UPDATE account SET money = money + 1000 WHERE NAME = '李四';

COMMIT;
ROLLBACK;

和方式一的区别就是开启事务的方式

START TRANSACTION;
#或
BEGIN

事务的四大特性(ACID)

既然谈到了事务,那么就必然离不开事务的四大特性

  • 原子性(atomicity)
    原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败。比如在同一个事务中的SQL语句,要么全部执行成功,要么全部执行失败。
  • 一致性(consistency)
    事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
    换一种方式理解就是:事务按照预期生效,数据的状态是预期的状态。
    举例说明:张三向李四转100元,转账前和转账后的数据是正确的状态,这就叫一致性,如果出现张三转出100元,李四账号没有增加100元这就出现了数据错误,就没有达到一致性。
  • 隔离性(isolation)
    事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
  • 持久性(durability)
    持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

并发事务存在的三个问题

  • 脏读
    事务A读到了事务B未提交的数据
  • 不可重复读
    事务A1读取id为1的数据,然后事务B1修改了id为1的数据,事务A2再次读取id为1的数据,发现两次结果不一致,这就是不可重复读。(A1、A2是指一个事务中的两次sql操作)
  • 幻读
    事务A1读取id为1的数据,发现为null,然后事务B1添加id为1的数据。此时事务A2向DB中添加id为1的数据,发现已经存在了。而查询id为1的数据仍然为空。这个id为1的数据对于事务A来说就像幽灵一样。

为了解决脏读,不可重复读,幻读,InnoDB存储引擎提供了四个隔离级别。

事务的隔离级别

  • 读未提交(read uncommitted)
  • 读已提交(read committed)
  • 可重复读(repeatable read)
  • 串行化(serializable)

下图为隔离级别与可以防止的事务。
√代表会发生,×代表不会发生
MYSQL数据库事务与事务的隔离级别_第2张图片

读未提交

读未提交的隔离级别下,脏读、不可重复读、幻读都有可能出现。

读已提交

读已提交的隔离级别下,脏读不会出现。
脏读是指事务A读到了事务B未提交的数据。
读已提交的隔离级别下,事务A只会读到事务B提交后的数据。

可重复读

可重复读的隔离级别下,脏读不可重复读不会出现
不可重复读是指事务A1读取id为1的数据,然后事务B1修改了id为1的数据,事务A2再次读取id为1的数据,发现两次结果不一致。(A1、A2是指一个事务中的两次sql操作)
在可重复读的隔离级别下,事务A中的不同的查询操作都会在本事务的范围之类,不会受到事务B的影响。

串行化

所有并发事务问题都不会发生,因为它会给每一个进入数据库的事务加“锁”,只有等当前事务结束释放锁后,下一个事务才会进入。所以就避免了并发事务问题。

查询和设置隔离级别

需要注意的是,mysql中的默认存储引擎是innodb,它默认的隔离级别是可重复读。

#查询隔离级别
select @@Transaction;
#设置隔离级别
#set [session|global] Transaction isolation level {read uncommitted|read committed|repeatable read|serializable}
set session transaction isolation level repeatable read

你可能感兴趣的:(数据库,mysql,sql)