【Linux】Mysql事务

一、什么是事务

Mysql 数据库中不是所有的存储引擎都实现了事务处理。

  • 支持事务的存储引擎有:
    • InnoDB
    • NDB Cluster 。
  • 不支持事务的存储引擎代表有:
    • MyISAM 

事务简单来说:一个 Session 中所进行所有的操作,要么同时成功,要么同时失败。进一步说,事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。【Linux】Mysql事务_第1张图片


【 语法 】

mysqlbinlog -v 数据库的二进制日志

mysqlbinlog -v mysql-bin.000001

该命令可以用来查看数据库二进制日志的详情,二进制日志里存放的就是数据库进行的操作也就是事务,事务由BEGIN开启,由COMMIT提交

【Linux】Mysql事务_第2张图片


  • 事务就是一组原子性的 SQL 语句。具体来说,事务指的是满足 ACID 特性的一组操作。
  • 事务内的 SQL 语句,要么全执行成功,要么全执行失败。
  • 通过加锁的方式,可以实现不同的事务隔离机制。
  • 想象一下,如果没有事务,在并发环境下,就可能出现丢失修改的问题。
    • T1 和 T2 两个线程都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。

【Linux】Mysql事务_第3张图片

二、事务用法

1)事务处理指令

Mysql 中,使用 START TRANSACTION 语句开始一个事务;使用 COMMIT 语句提交所有的修改;使用 ROLLBACK 语句撤销所有的修改。不能回退 SELECT 语句,回退SELECT 语句也没意义;也不能回退 CREATE 和 DROP 语句。只能回退INSERT语句


  • START TRANSACTION - 指令用于标记事务的起始点。
  • SAVEPOINT - 指令用于创建保留点。
  • ROLLBACK TO - 指令用于回滚到指定的保留点;如果没有设置保留点,则回退START TRANSACTION 语句处。
  • COMMIT - 提交事务。

2)事务处理示例:

(1)创建一张示例表
-- 创建表 user

CREATE TABLE user (
id int(10) unsigned NOT NULL COMMENT 'Id',
username varchar(64) NOT NULL DEFAULT 'default' COMMENT '用户
名',
password varchar(64) NOT NULL DEFAULT 'default' COMMENT '密码',
email varchar(64) NOT NULL DEFAULT 'default' COMMENT '邮箱'

) COMMENT='用户表';


【Linux】Mysql事务_第4张图片


(2)执行事务操作
-- 开始事务

START TRANSACTION;


-- 插入操作 A

INSERT INTO `user`
VALUES (1, 'root1', 'root1', '[email protected]');


-- 创建保留点 updateA

SAVEPOINT updateA;


-- 插入操作 B
 

INSERT INTO `user`
VALUES (2, 'root2', 'root2', '[email protected]');


-- 回滚到保留点 updateA
 

ROLLBACK TO updateA;


-- 提交事务,只有操作 A 生效
 

COMMIT;


 (3)执行结果
 

SELECT * FROM user;

【Linux】Mysql事务_第5张图片
 

 【注意,想要ROLLBACK不创建保留点也能ROLLBACK】


3)自动提交(AUTOCOMMIT)

MySQL 默认采用隐式提交策略( autocommit )。每执行一条语句就把这条语句当成一个事务然后进行提交。也就是使用BEGIN开启事务的话默认为隐式提交策略,当出现 START TRANSACTION 语句时,会关闭隐式提交;当COMMIT 或 ROLLBACK 语句执行后,事务会自动关闭,重新恢复隐式提交。

通过 set autocommit=0 可以取消自动提交,直到 set autocommit=1 才会提交; autocommit 标记是针对每个连接而不是针对服务器的。

【Linux】Mysql事务_第6张图片


-- 查看 AUTOCOMMIT
SHOW VARIABLES LIKE 'AUTOCOMMIT';


-- 关闭 AUTOCOMMIT
SET autocommit = 0;


-- 开启 AUTOCOMMIT
SET autocommit = 1;

【Linux】Mysql事务_第7张图片

三、事务特性

ACID 是数据库事务正确执行的四个基本要素。

  • 原子性(Atomicity)
    • 事务被视为不可分割的最小单元,事务中的所有操作要么全部提交成功,要么全部失败回滚。
    • 回滚可以用日志来实现,日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。
  • 一致性(Consistency)
    • 数据库在事务执行前后都保持一致性状态。
    • 在一致性状态下,所有事务对一个数据的读取结果都是相同的。
  • 隔离性(Isolation)
    • 一个事务所做的修改在最终提交以前,对其它事务是不可见的。
  • 持久性(Durability)
    • 一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。
    • 可以通过数据库备份和恢复来实现,在系统发生奔溃时,使用备份的数据库进行数据恢复。

一个支持事务(Transaction)中的数据库系统,必需要具有这四种特性,否则在事 务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达 不到交易。

  • 只有满足一致性,事务的执行结果才是正确的。
  • 在无并发的情况下,事务串行执行,隔离性一定能够满足。此时只要能满足原子 性,就一定能满足一致性。
  • 在并发的情况下,多个事务并行执行,事务不仅要满足原子性,还需要满足隔离 性,才能满足一致性。
  • 事务满足持久化是为了能应对系统崩溃的情况。

【Linux】Mysql事务_第8张图片


MySQL 默认采用自动提交模式( AUTO COMMIT )。也就是说,如果不显式使用 START TRANSACTION 语句来开始一个事务,那么每个查询操作都会被当做一个事务 并自动提交。 

四、事务隔离级别

1)事务隔离简介

在并发环境下,事务的隔离性很难保证,因此会出现很多并发一致性问题:

  • 丢失修改
  • 脏读
  • 不可重复读
  • 幻读

在 SQL 标准中,定义了四种事务隔离级别(级别由低到高):

  • 未提交读(READ UNCOMMITTED)
  • 提交读(READ COMMITTED)
  • 可重复读(REPEATABLE READ)
  • 串行化(SERIALIZABLE)

Mysql 中查看和设置事务隔离级别:

-- 查看事务隔离级别
SHOW VARIABLES LIKE 'transaction_isolation';


-- 设置事务隔离级别为 READ UNCOMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;


-- 设置事务隔离级别为 READ COMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;


-- 设置事务隔离级别为 REPEATABLE READ
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;


-- 设置事务隔离级别为 SERIALIZABLE
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

1、读未提交(READ UNCOMMITTED)

读未提交是指:事务中的修改,即使没有提交,对其它事务
也是可见的。
读未提交的问题:事务可以读取未提交的数据,也被称为 脏读(Dirty Read)。
T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的
数据是脏数据。

【Linux】Mysql事务_第9张图片


脏读

脏读是指一个事务未提交前,另一个事务就读取了它所修改的数据。这种读取的数据 是未提交的,也就是 脏 的,因此被称作是脏读。如果第一个事务在后续操作中回滚 了事务,那么第二个事务读取到的脏数据也就是无效的,这样会导致数据不一致。 


在Mysql中可以使用如下命令修改当前会话的事务隔离级别,

SET TRANSACTION ISOLATION LEVEL 隔离级别;

其中隔离级别可以为:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 或 SERIALIZABLE。该方式只是将当前会话的隔离级别设置为指定值。


如果需要修改所有连接默认的事务隔离级别,可以通过配置文件中修改:

transaction-isolation = 隔离级别

2、读已提交

提已交读(READ COMMITTED) 是指:事务提交后,其他事务才能看到它的修改。换
句话说,一个事务所做的修改在提交之前对其它事务是不可见的。提交读解决了脏读的问题。


提已交读是大多数数据库的默认事务隔离级别。


提已交读有时也叫不可重复读,它的问题是:执行两次相同的查询,得到的结果可能不一致。


T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的
结果和第一次读取的结果不同。
【Linux】Mysql事务_第10张图片


 3、不可重复读

不可重复读是指在同一个事务中,多次读取同一行数据,但是读取的结果不一致的现 象。例如事务A在读取一行数据时,事务B对该行数据进行了修改并提交了事务。如 果事务A再次读取该行数据,将会读取到修改后的数据。

【Linux】Mysql事务_第11张图片【Linux】Mysql事务_第12张图片


4、可重复读

可重复读(REPEATABLE READ) 是指:保证在同一个事务中多次读取同样数据的结果
是一样的。可重复读解决了不可重复读问题。


可重复读是 Mysql 的默认事务隔离级别。


可重复读的问题:当某个事务读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务又再次读取该范围的记录时,会产生 幻读(Phantom Read)。


T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的
数据,此时读取的结果和和第一次读取的结果不同。
 【Linux】Mysql事务_第13张图片


5、幻读

幻读是指在一个事务中,多次执行相同的查询,但是每次查询返回的结果集却不一致
的现象。通常情况下,幻读是由于其他事务在该事务执行期间插入或者删除了满足该
查询条件的行,导致查询的结果集发生了变化。

(相当于你查看这个数据,它现在为A,他去对这个数据进行了修改,你再查看发现数据变了,你很纳闷:我明明没改数据,为啥我两次查看速度数据不一致?这就是幻读)

假设事务A在查询某个表中所有符合条件的行,得到了结果集X,然后再该事务执行
期间,事务B查询了一条符合条件的记录,当事务A再次执行同样的查询时,得到的
结果集就包含了新插入的记录。

假设事务A在查询某个表中所有符合条件的行,得到了结果集X,然后再该事务执行
期间,事务B查询了一条符合条件的记录,当事务A再次执行同样的查询时,得到的
结果集就包含了新插入的记录。
【Linux】Mysql事务_第14张图片

【Linux】Mysql事务_第15张图片【Linux】Mysql事务_第16张图片 


6、串行化 

 串行化(SERIALIXABLE) 是指:强制事务串行执行。


在Mysql的事务隔离级别中,最高的级别就是SERIALIZABLE它提供了最高的数据
一致性和安全性,但也是性能最低的隔离级别。


在该隔离级别下,事务之间是完全隔离的,每个事务只能按照顺序逐个执行,任何两
个事务不能并发执行。这就相当于所有事务都是串行化执行的,因此也被称为串行
化。在该隔离级别下,前面提到的脏读、不可重复读和幻读等问题都被解决了。


强制事务串行执行,则避免了所有的并发问题。串行化策略会在读取的每一行数据上
都加锁,这可能导致大量的超时和锁竞争。这对于高并发应用基本上是不可接受的,
所以一般不会采用这个级别。


2)隔离级别小结

  • 读未提交(READ UNCOMMITTED) - 事务中的修改,即使没有提交,对其它事务也是可见的。
  • 读已提交(READ COMMITTED) - 一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。
  • 可重复读(REPEATABLE READ) - 保证在同一个事务中多次读取同样数据的结果是一样的。
  • 串行化(SERIALIXABLE) - 强制事务串行执行。

数据库隔离级别解决的问题:

【Linux】Mysql事务_第17张图片

你可能感兴趣的:(Linux,MySql,mysql,数据库,linux)