MySQL数据库——事务

事务简介

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

默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务。


事务操作

方式一:修改事务的提交方式

  • 查看/设置事务提交方式
SELECT @@autocommit;
SET @@autocommit = 0; -- 将事务提交方式改为手动提交;1-自动提交(默认)
  • 提交事务
COMMIT;
  • 回滚事务
ROLLBACK;

方式二:开启事务

  • 开启事务
START TRANSACTION 或 BEGIN;
  • 提交事务
COMMIT;
  • 回滚事务
ROLLBACK;

事务的四大特性ACID

  • 原子性 (Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
  • 一致性 (Consistency):事务完成时,必须使所有的数据都保持一致状态。

        

  • 隔离性 (lsolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
  • 持久性 (Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

        


并发事务问题

问题描述
脏读一个事务读到另外一个事务还没有提交的数据。
不可重复读一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
幻读一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了“幻影”

脏读

一个事务读到另外一个事务还 没有提交 的数据。

  • 事务A的第一个操作查询(SELECT)了一个 id=1 的数据;
  • 事务A的第二个操作更新(UPDATE)了 id=1 的数据;
  • 此时事务A还未执行完操作并提交事务,然后事务B进来了;
  • 事务B执行了查询 id=1 的数据;
  • 此后如果事务A因为某种原因撤销对该值的修改,这就导致了事务B所读取到的数据是无效的

不可重复读

一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。

  • 事务A先执行了查询(SELECT)  id=1 的数据;
  • 此时事务B的执行了一个更新(UPDATE) id=1 的数据的操作,且已经提交到数据库(数据库中前后数据不一致了);
  • 此时事务A还未执行完操作并提交事务,然后事务B进来了;
  • 事务B执行了查询 id=1 的数据;
  • 此后如果事务A因为某种原因撤销对该值的修改,这就导致了事务B所读取到的数据是无效的

幻读

幻读是不可重复读的一种特殊场最。一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了“幻影”

  • 事务A的第一个操作先执行了查询(SELECT)  id=1 的数据,发现没有该数据;
  • 此时事务B的执行了一个插入(INSERT) id=1 的数据的操作,且已经提交到数据库;
  • 然后事务A执行第二个操作插入(INSERT) id=1 的数据,由于id主键的唯一性,所以运行这条插入语句时会报错(数据库中已存在id=1的数据了);
  • 事务A执行第三个操作查询(SELECT) id=1 的数据时,因为前面的不可重复读的概念,所以再次查询的时候id=1的数据是一定没有的;
  • 此时“幻影”就出现了,明明插入了呀?怎么查不到呢?

事务隔离级别

脏读、不可重复读和幻读这三种异常情况,是在 SQL-92 标准中定义的,同时 SQL-92 标准还定义了 4 种隔离级别来解决这些异常情况,从高到底依次为:顺序执行(Serializable)、可重复读(Repeatable reads)、提交读(Read committed)、未提交读(Read uncommitted)。

隔离级别脏读不可重复读幻读
未提交读(Read uncommitted)
提交读(Read committed)×
可重复读(Repeatable reads)-默认××
串行化(Serializable)×××

注:Oracle的默认事务隔离级别是 提交读(Read committed)

未提交读(Read uncommitted)

未提交读(Read uncommitted)是最低的隔离级别。通过名字我们就可以知道,在这种事务隔离级别下,一个事务可以读到另外一个事务未提交的数据。这种隔离级别下会存在幻读、不可重复读和脏读的问题。

提交读(Read committed)

提交读(Read committed)也可以翻译成读已提交,通过名字也可以分析出,在一个事务修改数据过程中,如果事务还没提交,其他事务不能读该数据。所以,这种隔离级别是可以避免脏读的发生的。

可重复读(Repeatable reads)

可重复读(Repeatable reads),由于提交读隔离级别会产生不可重复读的读现象。所以,比提交读更高一个级别的隔离级别就可以解决不可重复读的问题。这种隔离级别就叫可重复读。但是这种隔离级别没办法彻底解决幻读。

可串行化(Serializable)

可串行化(Serializable)是最高的隔离级别,前面提到的所有的隔离级别都无法解决的幻读,在可串行化的隔离级别中可以解决。


查看事务隔离级别

--  查看事务隔离级别
SELECT @@TRANSACTION_ISOLATION;

设置事务隔离级别

-- 设置事务隔离级别
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED |  REPEATABLE READ | SERIALIZABLE}

-- SESSION: 只对当前会话(连接)有效,仅对当前客户端窗口有效
-- GLOBAL: 设置全局默认隔离级别,不影响当前已存在的会话,针对于所有客户端的窗口有效

注意:事务隔离级别越高,数据越安全,但是性能越低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值