《MySQL——事务》

目录

  • 事务的必要性
  • MySQL中如何控制事务
  • 手动开启事务
  • 事务的四大特征
    • 事务的四大特征
    • 事务开启方式
    • 事务手动提交与手动回滚
  • 事务的隔离性
    • 脏读现象
    • 不可重复读现象
    • 幻读现象
    • 串行化
  • 一些补充
    • 使用长事务的弊病
    • `commit work and chain`的语法是做什么用的?
    • 怎么查询各个表中的长事务?
    • 如何避免长事务的出现?
    • 事务隔离是怎么通过read-view(读视图)实现的?
  • 参考

事务的必要性

mysql中,事务是一个最小的不可分割的工作单元。事务能够保证一个业务的完整性。
比如我们的银行转账:

-- a -> -100
UPDATE user set money = money - 100 WHERE name = 'a';-- b -> +100
UPDATE user set money = money + 100 WHERE name = 'b';

如果程序中,只有一条语句执行成功了,而另外一条没有执行成功,就会出现前后不一致。就会有人白嫖。
因此,在执行多条有关联 SQL 语句时,事务可能会要求这些 SQL 语句要么同时执行成功,要么就都执行失败。
也就是说事务具有原子性。

MySQL中如何控制事务

1、mysql是默认开启事务的(自动提交)
默认事务开启的作用:

-- 查询事务的自动提交状态
SELECT @@AUTOCOMMIT;
+--------------+
| @@AUTOCOMMIT |
+--------------+
|            1 |
+--------------+

当我们执行一个sql语句时候,效果会立即体现出来,且不能回滚。
回滚举例

CREATE DATABASE bank;USE bank;CREATE TABLE user (id INT PRIMARY KEY,name VARCHAR(20),money INT
);INSERT INTO user VALUES (1, 'a', 1000);SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
+----+------+-------+

执行插入语句后数据立刻生效,原因是 MySQL 中的事务自动将它提交到了数据库中。那么所谓回滚的意思就是,撤销执行过的所有 SQL 语句,使其回滚到最后一次提交数据时的状态。

在 MySQL 中使用 ROLLBACK 执行回滚:
由于所有执行过的 SQL 语句都已经被提交过了,所以数据并没有发生回滚。

-- 回滚到最后一次提交
ROLLBACK;SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
+----+------+-------+

将自动提交关闭后,可以数据回滚:

-- 关闭自动提交
SET AUTOCOMMIT = 0;-- 查询自动提交状态
SELECT @@AUTOCOMMIT;
+--------------+
| @@AUTOCOMMIT |
+--------------+
|            0 |
+--------------+

现在我们测试一下:

INSERT INTO user VALUES (2, 'b', 1000);-- 关闭 AUTOCOMMIT 后,数据的变化是在一张虚拟的临时数据表中展示,
-- 发生变化的数据并没有真正插入到数据表中。
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+-- 数据表中的真实数据其实还是:
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
+----+------+-------+-- 由于数据还没有真正提交,可以使用回滚
ROLLBACK;-- 再次查询
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
+----+------+-------+

可以使用COMMIT将虚拟的数据真正提交到数据库中:

INSERT INTO user VALUES (2, 'b', 1000);
-- 手动提交数据(持久性),
-- 将数据真正提交到数据库中,执行后不能再回滚提交过的数据。
COMMIT;-- 提交后测试回滚
ROLLBACK;-- 再次查询(回滚无效了)
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+

总结

1、查看自动提交状态: select @@AUTOCOMMIT;
2、设置自动提交状态: set AUTOCOMMIT = 0;
3、手动提交: 在 @@AUTOCOMMIT = 0 时,可以使用commit 命令提交事务
4、事务回滚: 在 @@AUTOCOMMIT = 0 时,可以使用rollback 命令回滚事务

事务给我们提供了一个可以反悔的机会,假设在转账时发生了意外,就可以使用 ROLLBACK 回滚到最后一次提交的状态。假设数据没有发生意外,这时可以手动将数据COMMIT 到数据表中。

手动开启事务

可以使用BEGIN 或者 START TRANSACTION 手动开启一个事务。

-- 使用 BEGIN 或者 START TRANSACTION 手动开启一个事务
-- START TRANSACTION;
BEGIN;
UPDATE user set money = money - 100 WHERE name = 'a';
UPDATE user set money = money + 100 WHERE name = 'b';-- 由于手动开启的事务没有开启自动提交,
-- 此时发生变化的数据仍然是被保存在一张临时表中。
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
+----+------+-------+-- 测试回滚
ROLLBACK;SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+

当然事务开启之后,使用commit提交后就不能回滚了。

事务的四大特征

事务的四大特征

A 原子性:事务是最小的单位,不可以分割
C 一致性:事务要求同一事务中的sql语句,必须要保证同时成功或者同时失败
I 隔离性:事务1 和事务2 之间是具有隔离性的
D 持久性:事务一旦结束(commit or rollback),就不可以返回

事务开启方式

1、修改默认提交 set autocommit = 0;
2、begin
3、start transaction

事务手动提交与手动回滚

手动提交:commit
手动回滚:rollback

事务的隔离性

事务的隔离性:

1、read uncommitted; 读未提交的
2、read committed; 读已经提交的
3、repeatable read; 可以重复读
4、serializable; 串行化

脏读现象

read uncommitted的隔离级别下:
脏读:一个事务读到了另外有一个事务没有提交的数据
实际开发不允许脏读出现。
如果有两个事务 a、b
a事务对数据进行操作,在操作的过程中,事务并没有被提交,但是b可以看见a操作的结果。b看到转账到了,然后就不管了。后面a进行rollback操作,钱又回去了,完成白嫖。

不可重复读现象

read committed的隔离级别下:
小王一开始开启了一个事务,然后提交了几个数据,然后出去抽烟。
在他抽烟的时候,小明在其他电脑上开启了一个事务,然后对那个表提交了一个数据。
小王烟抽完了,然后统计表中数据,发现不对劲。前后不一致了。

幻读现象

repeatable read;的隔离级别下:
事务a和事务b同时操作一张表,事务a提交的数据也不能被事务b读到,就可以造成幻读。
可以观察如下步骤:
小明 在杭州 开启一个事务;
小王 在北京 开启一个事务;
小明 对table进行插入数据操作,然后commit;然后查看表,发现操作成功
小王在对table进行插入之前也查看表,然而并没有小明插入的数据,于是乎他插入了同样的一条数据,数据库报错。
小王很是疑惑,这就是幻读现象。

串行化

serializable的隔离级别下:
当user表被事务a操作的时候,事务b里面的写操作是不可以进行的,会进入排队状态(串行化)。
“读-读”在串行化隔离级别允许并发。
直到事务a结束之后,事务b的写入操作才会执行。
串行化的问题是性能特差。
一般来说,隔离级别越高,性能越差。
MySQL默认隔离级别是:repeatable read;

一些补充

使用长事务的弊病

存储空间上来说:
长事务意味着系统里面会存在很老的事务视图。由于这些事务随时可能访问数据库里面的任何数据,所以这个事务提交之前,数据库里面它可能用到的回滚记录都必须保留,这就会导致大量占用存储空间。
长事务还占用锁资源,也可能拖垮整个库。

commit work and chain的语法是做什么用的?

提交上一个事务,并且再开启一个新的事务。它的功能等效于:commit + begin

怎么查询各个表中的长事务?

这个表中记录了所有正在运行的事务信息,里面有事务的开始时间。可以从这里看出哪些事务运行的时间比较长。

select * from information_schema.innodb_trx;

如何避免长事务的出现?

数据库方面:

a.设置autocommit=1,不要设置为0。
b.写脚本监控information_schemal.innodb_trx表中数据内容,发现长事务,kill掉它。
c.配置SQL语句所能执行的最大运行时间,如果查过最大运行时间后,中断这个事务

SQL语句方面:

设置回滚表空单独存放,便于回收表空间

业务代码方面:

1、检查业务逻辑代码,能拆分为小事务的不要用大事务。
2、检查代码,把没有必要的select语句被事务包裹的情况去掉

事务隔离是怎么通过read-view(读视图)实现的?

每一行数有多个版本,当我们要去读取数据的时候,要判断这个数据的版本号,对当前事务而言,是否可见,如果不可见,则要根据回滚日志计算得到上一个版本。如果上一个版本也不符合要求,则要找到再上一个版本,
直到找到对应正确的数据版本。

参考

一天学会MySQL
https://time.geekbang.org/column/article/68963

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

运行在TQ2440开发板上以及X86平台上的linux内核编译

一、运行在TQ2440开发板上的linux内核编译 1、获取源码并解压 直接使用天嵌移植好的“linux-2.6.30.4_20100531.tar.bz2”源码包。 解压(天嵌默认解压到/opt/EmbedSky/linux-2.6.30.4/中) tar xvjf linux-2.6.30.4_20100531.tar.bz2 -C / 2、获取默认配置…

ArcCatalog ArcMap打不开

原来是因为: 连接了电信的无线网卡 关掉即可 启动ArcCatalog之后再开启无线网卡 没问题!转载于:https://www.cnblogs.com/ccjcjc/archive/2012/08/21/2649867.html

Python熊猫– GroupBy

Python熊猫– GroupBy (Python Pandas – GroupBy) GroupBy method can be used to work on group rows of data together and call aggregate functions. It allows to group together rows based off of a column and perform an aggregate function on them. GroupBy方法可用…

MySQL索引底层原理理解以及常见问题总结

目录二叉查找树为索引红黑树为索引B树作为索引B树作为索引MyISAM存储引擎索引实现InnoDB存储引擎索引实现常见问题聚集索引与非聚集索引InnoDB基于主键索引和普通索引的查询有什么区别?InnoDB主键索引为何是整型的自增主键何时使用业务字段作为主键呢?哈…

Spring之HibernateTemplate 和HibernateDaoSupport

spring提供访问数据库的有三种方式: HibernateDaoSupport HibernateTemplate(推荐使用) jdbcTemplate(我们一般不用) 类所在包: HibernateTemplate:org.springframework.orm.hibernate3.HibernateTemplate …

JDOJ-重建二叉树

这是一道面试题,可以说是数据结构中的基础题了,由先序遍历以及中序遍历生成一棵树,然后输出后序遍历。 一个递归函数传递5个参数,顶点编号,先序左右区间,中序左右区间,每次进行区间长度判定&…

des算法密码多长_密码学中的多个DES

des算法密码多长This is a DES that was susceptible to attacks due to tremendous advances in computer hardware in cryptography. Hence, it was a very complex or competent algorithm it would be feasible to reuse DES rather than writing an of cryptography. 由于…

《MySQL——索引笔记》

目录回表覆盖索引最左前缀原则联合索引的时候,如何安排索引内的字段顺序?索引下推重建索引问题联合主键索引和 InnoDB 索引组织表问题in与between的区别回表 回到主键索引树搜索的过程,我们称为回表。 覆盖索引 覆盖索引就是在这次的查询中…

计算凸多边形面积的算法

1. 思路: 可以将凸多边形(边数n > 3)划分为 (n - 2) 个三角形,分别运用向量叉积计算每个三角形的面积,最后累加各个三角形的面积就是多边形的面积。 2. 求多边形面积的算法模板:   定义点的结构体 str…

Windows CE开发常见问题解答

转自: http://blog.csdn.net/slyzhang/article/details/6110490 1.怎样在一个控件获得焦点时打开软键盘?比如一个EditBox获得焦点后,这个时候自动打开软键盘,这样可以方便用户输入——SIPINFO、SHSIPINFO、SIPSETINFO、SIPGETINFO…

Julia中的supertype()函数

Julia| supertype()函数 (Julia | supertype() function) supertype() function is a library function in Julia programming language, it is used to get the concrete supertype of the given type (data type). supertype()函数是Julia编程语言中的库函数,用于…

《操作系统知识点整理》

目录进程与线程比较多线程同步与互斥生产者与消费者哲学家就餐问题读者写者问题进程间通信管道消息队列共享内存信号量信号Socket锁互斥锁与自旋锁读写锁乐观锁与悲观锁死锁进程与线程比较 进程是资源(包括内存、打开的文件等)分配的单位,线…

for,foreach,iterator的用法和区别

相同点&#xff1a; 三个都可以用来遍历数组和集合不同点&#xff1a;1.形式差别 for的形式是 for&#xff08;int i0;i<arr.size();i&#xff09;{...} foreach的形式是 for&#xff08;int i&…

和菜鸟一起学linux总线驱动之初识spi驱动主要结构

既然知道了协议了&#xff0c;那么就可以开始去瞧瞧linux kenerl中的spi的驱动代码了&#xff0c;代码中有很多的结构体&#xff0c;还是对主要的结构体先做个了解吧&#xff0c;那样才可以很好的理解驱动。主要是include/linux/spi.h 首先是SPI的主机和从机通信接口&#xff0…

操作系统大内核和微内核_操作系统中的内核

操作系统大内核和微内核A Kernel is the central component of an Operating System. The Kernel is also said to be the heart of the Operating System. It is responsible for managing all the processes, memory, files, etc. The Kernel functions at the lowest level …

《MySQL——锁》

全局锁是什么&#xff1f;全局锁有什么用&#xff1f;全局锁怎么用&#xff1f; 全局锁主要用在逻辑备份过程中&#xff0c;对于InnoDB 引擎的库&#xff0c;使用–single-transaction; MySQL 提供了一个加全局读锁的方法&#xff0c;命令是 Flush tables with read lock (FTW…

搜索引擎Constellio及Google Search Appliances connectors

做搜索产品的时候发现国外一个同类型的产品contellio&#xff0c;发现功能比较强大&#xff0c;先记录下来 貌似可以添加文档 网站 以及数据库等不同类型的数据源 http://wiki.constellio.com/index.php/Main_Page http://www.constellio.com/ http://www.constellio.com htt…

dig下载_DIG的完整形式是什么?

dig下载DIG&#xff1a;副监察长 (DIG: Deputy Inspector General) DIG is an abbreviation of the Deputy Inspector General. It is a high-level position in the Indian Police Service. The officers who already offered service on Senior Superintendent of Police (SS…

分类器是如何做检测的?——CascadeClassifier中的detectMultiScale函数解读

原地址&#xff1a;http://blog.csdn.net/delltdk/article/details/9186875 在进入detectMultiScal函数之前&#xff0c;首先需要对CascadeClassifier做初始化。 1. 初始化——read函数 CascadeClassifier的初始化很简单&#xff1a; cv::CascadeClassifier classifier; cl…

<MySQL>何时使用普通索引,何时使用唯一索引

如果能够保证业务代码不会写入重复数据&#xff0c;就可以继续往下看。 如果业务不能保证&#xff0c;那么必须创建唯一索引。 关于查询能力 普通索引和唯一索引在查询能力上是没有很大差别的。 如&#xff1a;select id from T where k5 1、普通索引查找到满足条件的第一个记…