MYSQL 事务的隔离性(1)

【MySQL】深度理解事务的隔离性:全面讲解事务的四种隔离级别 *前言:**上节内容我们主要说了如果没有设置保存点,也可以回滚,但是只能回滚到事务的开始。直接使用rollback的前提是事务还没有提交。并且如果一个事务被提交了,就不可以回退。同时我们也可以使用savepoint设置回滚点。可以自己选择想要回滚到的位置。同时最后我们也提到了,InnoDB支持事务,但是MyISAM不支持事务。这节就将更深入的使用事务。看一下事物的特性——隔离性。下面友友们开始学习吧! 阅读详情

文章目录

认识事务的隔离性

认识事务的隔离级别

如何理解事务的原子性?

一个事务中可以有多条sql语句,也就是说一条事务可能会对数据库做很多操作。而事务的原子性指的就是,一条事务内的多条sql语句是同生共死的,他们要么一起执行,要么都不会被执行,不会出现事务结束之后一些语句执行成功,另外一些执行失败的情况。如果这个事务的某条操作执行过程中遇到了点问题,没法顺利完成,那其余的操作也不会执行,mysql会把数据库恢复到事务开始之前的状态

一个事务可能由多条SQL构成,也就意味着,任何一个事务,都有执行前,执行中,执行后的阶段。而所谓的原子性,其实就是让用户层,要么看到执行前,要么看到执行后。事物执行中出现问题,执行不下去了,就立即回滚到执行前。

事务的隔离级别有哪些?

  1. 读未提交(Read Uncommitted)
  2. 读已提交(Read Committed)
  3. 可重复读(Repeatable Read)
  4. 串行化(Serializable)

为什么要划分四种隔离级别?

隔离级别存在的意义是什么?为什么要划分出来这些隔离级别?如果是要解决多请求并发问题,那我给线程访问临界资源的动作上锁不就行了吗?

引入隔离级别最大的原因在于,mysql不仅想解决多请求并发处理问题,实现多线程对数据库的安全访问,还想在保证安全性的基础上,最大程度地提高执行效率(mysql想既要还要)。

四种隔离级别对安全性和执行效率做的平衡是不一样的。比如串行化,它是最安全的,但是执行效率是最慢的,读未提交(Read Uncommitted)是最不安全的,但是执行效率是最快的。如果单单是为了解决多请求并发处理的安全问题,那确实简单,直接上锁(对应串行化)就行了。但是在具体的场景中,可能有些场景不容易出现安全性的问题,不需要你给他提供那么严格的安全性保障,那我们就可以更弱一些的隔离级别,牺牲一部分安全性,从而为mysql运行换来更高的性能。

前面说的加锁,确实可以解决并发带来的数据不一致问题,但也是有缺点的,缺点是,你这种方式就让多线程访问临界资源时完全丧失了并发性。转化成了多线程串行执行,会导致各个线程的执行效率大大降低,这会直接影响到我们对数据库增删查改操作的执行效率

mysql对上述效率是很看重的,他想在确保安全性的基础上,尽可能提高进程执行的效率,于是就给隔离的程度划分了等级
像你刚刚说的那种方案,就是隔离等级的第四级,也就是最高级别的隔离,除此之外还有较低级别的三种隔离等级,等级越低的隔离越不安全,但效率越高。相当于用安全性去换效率

如何查看隔离级别?

隔离级别在宏观上又分为全局事务隔离级别和会话事务隔离级别,这俩含义也是不一样的

MSYQL中的会话是什么

一个MYSQL的会话 对应 一个客户端与MYSQL服务器之间建立起来的一个链接。连接是会话的 “物理载体”,一个连接对应一个会话,无论发起连接的客户端是否相同(比如是同一台电脑的 Navicat、同一程序的不同线程),只要是两次独立的连接请求(即建立了两条独立的 TCP 通信链路),MySQL 服务器就会为每一次连接分配独立的 “会话资源”

全局事务隔离级别和会话事务隔离级别有啥区别?

全局的可以管所有会话,当你修改了全局事务隔离级别之后,后面创建的新会话事务,其默认隔离级别就是你新改的全局事务隔离级别
会话事务隔离级别就管着这一个事务,当你修改了会话事务隔离级别之后,当前这个事务的隔离级别会变成你修改的那个值,但是后续新创建的事务隔离级别仍然由全局的隔离级别决定

如何查看当前全局事务的隔离级别?

select @@global.tx_isolation;
其中@@ 是用于引用系统变量的符号。也就是说tx_isolation是一个系统变量

如何查看当前会话事务的隔离级别?

select @@session.tx_isolation;
或者我们也可以直接输入select @@tx_isolation;它表示的也是当前会话事务的隔离级别

如何更改/设置隔离级别

如何更改/设置全局事务隔离级别?设置全局事务隔离级别有啥作用?

SET GLOBAL TRANSACTION ISOLATION LEVEL + 具体的隔离级别;
其中具体的隔离级别是我们前面说过的那四种中的一种

  1. READ - UNCOMMITTED读未提交
  2. READ - COMMITTED(读已提交)
  3. REPEATABLE - READ(可重复读)
  4. SERIALIZABLE(串行化)

比如SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
执行这条语句之后,后面MYSQL创建出的新会话的隔离级别默认都是READ COMMITTED(执行该语句的当前会话的隔离级别不受影响)

如何设置当前会话的事务隔离级别?

SET SESSION TRANSACTION ISOLATION LEVEL + 具体的隔离级别;

比如 SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
这条语句执行之后,当前会话后面创建的新事务,隔离级别都是 READ COMMITTED。

但是如果当前会话结束了,假如说当前全局隔离级别设置的是REPEATABLE - READ(可重复读),那下次我创建一个新会话,该会话的默认事务隔离级别就不是 READ COMMITTED了,而是REPEATABLE - READ(可重复读)

一个已经开始的事务,其隔离级别还能改吗?

在 MySQL 中,一个已经开始的事务(活跃事务),其隔离级别无法被修改。一旦事务通过 START TRANSACTION(或隐式开启,如 autocommit=0 时的第一条 SQL)启动,它的隔离级别就被固定了,后续即使执行 SET TRANSACTION 或 SET SESSION TRANSACTION 语句,也不会影响这个正在进行的事务。

隔离级别修改指令的生效范围

输入上面更改隔离级别的指令之后,隔离级别会立即生效吗?当前还没提交的事务受不受影响?
执行SET GLOBAL TRANSACTION ISOLATION LEVEL + 具体的隔离级别;后,全局隔离级别会立即更新,但并不会对当前已有的会话产生影响。
执行SET SESSION TRANSACTION ISOLATION LEVEL + 具体的隔离级别;后,当前会话的事务隔离级别会立即更新,但并不会对当前会话正在进行中的事务产生影响

假如说当前会话隔离级别设置的是REPEATABLE - READ(可重复读),然后我在当前会话中执行SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;,将全局隔离级别设置READ COMMITTED,那请问当前会话创建的下一条事务,他的隔离级别是什么呢?

是当前会话的隔离级别REPEATABLE - READ(可重复读)。因为全局隔离级别的设置语句并不会改变当前会话的隔离级别

假如说当前会话隔离级别设置的是REPEATABLE - READ(可重复读),然后我在当前会话中执行SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;,将当前会话的隔离级别修改为READ COMMITTED,那请问当前会话创建的下一条事务,他的隔离级别是什么呢?

是当前会话修改之后的隔离级别READ COMMITTED

假如说当前会话隔离级别设置的是REPEATABLE - READ(可重复读),在当前会话中我创建了一个事务还没提交,这时候我在当前会话中执行SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;,将当前会话的隔离级别修改为READ COMMITTED,那么请问还没提交的那个事务,它的隔离级别是什么呢?

是REPEATABLE - READ(可重复读),该事务的隔离级别 以 当前会话创建该事务时的隔离级别 为准

登出再登录对隔离级别的影响

当你登出当前会话并重新登录后,服务器就会为当前的新链接创建一个新的会话。新的会话默认采用最新设置的全局隔离级别

假如说当前会话隔离级别设置的是REPEATABLE - READ(可重复读),然后我在当前会话中执行SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;,将全局隔离级别设置READ COMMITTED,然后我直接退出当前会话重新登录。进入新会话时,这个新会话的事务隔离级别就是READ COMMITTED了

具体认识四种隔离级别

1.读未提交【Read Uncommitted】

如何理解读未提交?

意思就是在这种隔离级别下,mysql允许其他事务查看一个事务未提交时的数据。这种隔离级别没有任何隔离性,效率最高。
既然他效率最高,那他安全性肯定是最低的。我现在就想问

读未提交的隔离性下存在哪些安全问题呢?

  1. 脏读问题
  2. 不可重复读问题
  3. 幻读问题

什么是脏读问题 ?

幻读和不可重复读问题我们后面在说,现在我们重点来认识一下脏读
首先我们来认识一下脏读操作,所谓的脏读操作指的是:一个事务读取到了另一个事务未提交的数据

脏读问题指的就是脏读操作带来的问题,即若一个事务读取了另一个事务未提交的数据,但另一个事务后续未提交,直接回滚了,那么先读取的事务拿到的数据就是无效的,基于该数据的操作也可能出错。

比如,银行转账时,事务 A 从账户 A 扣钱但未提交,事务 B 此时读取账户 A 余额,若事务 A 回滚,事务 B 读到的就是错误余额 。

2.读提交【Read Committed】

读提交是什么意思?

意思就是在这种隔离级别下,mysql允许其他事务查看一个事务提交之后更新的数据,但是不允许其他事物查看一个事务未提交时更新的数据
提交之前看不到,提交之后就能看到了

读提交的隔离性下,解决了哪些安全问题?还存在哪些安全问题?

  • 读提交的隔离性下,已经不存在脏读问题了(为什么?)
    因为在读提交的隔离性下,不允许在一个事务内部查看其他未提交事务的数据

  • 但是仍然存在下面两种问题:
    不可重复读问题(什么是不可重复读问题?)
    幻读问题(什么是幻读问题?)

你可以这么认为,设置读提交的隔离级别,主要就是为了解决脏读问题的,就是不允许其他的事务去读取一个未提交事务更新的数据。一个事务提交之前,他对数据库做的任何更新操作都不允许被其他事务看见。

3.可重复读 【Repeatable Read】

可重复读是什么意思?

什么是不可重复读?

想要理解可重复读,我们可以先理解一下什么叫做不可重复读
注意看这张图的右侧,同一个事务内,同样的读取,在不同的时间段(依旧还在事务操作中!),读取到了不同的值,这种现象叫做不可重复读(non reapeatable read)!!
在这里插入图片描述
不可重复读这个概念感觉和幂等这个概念挺像的。所谓幂等指的就是多次执行相同的操作,最终得到的结果与执行一次完全一致。在上图中右端客户端执行了两次相同的查询。操作但是得到的结果却是不同的。那么我们就称此时这个操作就是不幂等的。

什么是可重复读

那可重复读就是指:一个事务,在这个事务的生命周期内的任意时间读取数据库中的数据,得到的结果始终是相同的

可重复读在上一个隔离级别读已提交的基础上,又做了哪些限制?

上一个隔离级别读已提交,不允许其他事务读取一个没有提交的事务中更新的数据。但是如果一个事物已经提交了,此时其他运行中的事务就可以同步到数据库更新之后的新数据了。

可重复读继承了读已提交的约束,不允许事务在运行过程中查看未提交事务更新的数据,在这个基础上又做了进一步的限制:事务是看不到其运行过程中数据库的更新操作的。即一个事务在执行过程中,不允许查看在该事务运行过程中提交的事务的更新数据,该事务在运行过程中看到的,是该事务开始时的老数据库(数据库在该事务启动时的快照)

为什么要引入可重复读这个隔离级别?

原因就在于,上一个级别:读提交,存在着一个不可重复读的问题。可重复读这个隔离级别,就是为了解决不可重复读问题而设置的。那什么是不可重复读问题呢?

什么是不可重复读问题?

现在我有一个场景,公司年终的时候根据每个员工的业绩给员工颁奖,奖品的发放规则如下:

  • 将所有贡献值在300到500之间的员工名单筛选出来,给他们每个人发一个台灯
  • 将所有贡献值在500到800之间的员工名单筛选出来,给他们每个人发一个键盘
  • 将所有贡献值在800到2000之间的员工名单筛选出来,给他们每个人发一个手机
  • 将所有贡献值在2000以上的员工名单筛选出来,给他们每个人发一个电脑

在公司内部数据库处理这个奖品发放的业务中,我们需要先把每个奖品对应的员工给分好,然后发奖。对应的事务可能是:

mysql> begin;
mysql> select name from employee WHERE contribution BETWEEN 300 AND 500;
mysql> select name from employee WHERE contribution BETWEEN 500 AND 800;
mysql> select name from employee WHERE contribution BETWEEN 800 AND 2000;
mysql> select name from employee WHERE contribution >= 2000;
mysql> commit;

按照正常情况下,一张表中,每个人都只属于一个奖品区间,都只能获得一份奖品
但是这个时候有个人叫张三的,他想钻空子。张三同志的贡献值为300,当数据库执行第一条筛选语句时,把张三筛上去了,然后给张三发了一个台灯。在数据库执行第二条筛选语句前,张三迅速跑到mysql后台,输入了下面的语句,将给自己的贡献值加到了600

UPDATE employees SET contribution = 600 WHERE name = '张三';

这时候如果mysql的隔离级别是读已提交,虽然不允许事务读取一个未提交事务更新的数据,但是允许事务在其运行过程中看到其他已提交事务更新的数据。还记得我们前面说的吗,在自动提交的模式下,一条sql语句就是一个事务,也就是说发放奖品的那个事务在运行的过程中,是能够看到张三刚刚输入的那条UPDATE语句更新后的数据的!

假如说张三这条UPDATE语句提交的时间要早于发放奖品的那个事务第二句sql语句的执行,那么第二个sql语句执行的时候,他看到的张三的贡献值就是600,这时候它拉出来的第二个名单里,也会有张三。于是公司又给张三发了一个键盘。

同理,在数据库执行第三条筛选语句前,张三迅速跑到mysql后台,给自己的贡献值加到了900…,那第三条筛选语句拉出来的名单里依然有张三,于是公司又给张三发了一个手机。

这样下去最终的结果就是,四个奖品获奖名单中都有张三,张三一个人拿了四个奖品。这就是不可重复读带来的问题!

现在请问:在一个事务内多次读取同一份数据,数据的值保持不变,与在事务结束之后,正常select多次读取同一份数据,数据的值保持不变。这俩说法的区别在哪里?

在事务结束之后,正常select多次读取同一份数据,数据的值保持不变。这是由数据库的持久性保证的
在一个事务内多次读取同一份数据,数据的值保持不变,这是由会话的隔离性(可重复读级别的隔离性)保证的。如果当前访问该数据库的会话,它的隔离性要比可重复读要低,比如说是读提交或者读未提交,那就无法确保

可重复读的隔离性下,解决了哪些安全问题?还存在哪些安全问题?

解决了不可重复读和脏读的问题,但是还存在着幻读问题
注意:其实mysql解决了在可重复读的隔离性下出现的幻读问题,但是在大多数数据库软件中,可重复读的隔离性下都是存在幻读问题的

什么是幻读问题?

幻读(Phantom Read)是数据库事务并发场景中一种特殊的数据一致性问题,指在同一个事务内,两次执行相同的查询语句,却返回了不同的结果集(行数增减),如同出现了 “幻觉”。
具体来说,幻读的典型表现是:

  • 事务 A 第一次查询符合条件的记录,得到 N 条结果;
  • 事务 B 此时插入 / 删除了一条符合该条件的新记录并提交;
  • 事务 A 再次执行相同的查询,结果变成了 N+1 条(或 N-1 条),与第一次结果不一致。

可重复读的隔离级别下,存在幻读问题吗?

请思考下面的问题
我们将一个mysql客户端当前会话的隔离级别设定成可重复读,然后向表stu中插入了一个新的表项(我们把这个操作记为事务1),假如说这时候有另一个事务2正在运行中(该事务启动的时候这个表项是没有的),事务1插入完毕之后事务2进行select * from stu,能查出事务1新插入的表项吗?
可重复读的隔离级别下,数据一致性往往是通过对数据加锁实现的,但是对于一个并不存在的表项,数据库没有办法事先对这个表项中的数据进行加锁,所以有时候没有办法做到完全隔离。在很多数据库软件中,另一端select是能看到的
但是在MYSQL中,可以保证另一端select看不到
也就是说,在MYSQL中,可重复读的隔离条件下不存在幻读问题,但是在绝大多数数据库软件中,可重复读的隔离性下都是存在幻读问题的

为什么可重复读的隔离级别下会存在幻读问题?

这个答案我们在上个问题中说过了,但是为了强调,我们就再说一遍
可重复读的隔离级别下,数据一致性往往是通过对数据加锁实现的,但是对于一个并不存在的表项,数据库没有办法事先对这个表项中的数据进行加锁,所以有时候没有办法做到完全隔离。因此在很多数据库软件中,另一端select是能看到的这个刚刚插入的数据的

为什么MYSQL在可重复读的隔离级别下不会存在幻读问题?

因为MYSQL的数据一致性是通过快照机制实现的,MYSQL会在事务开始时给当前数据库拍一个快照,在RR的隔离级别下,事务在运行过程中访问的数据库,都是数据库在该事务启动时的快照。

因此,即使其他客户端在会话 A 的事务执行过程中插入并提交了新数据,会话 A 的事务也 “看不到” 这些变化,直到当前事务结束(COMMIT 或 ROLLBACK),后续新事务的查询才会基于新的快照。

更具体地来说,MySQL是用Next-Key锁解决的。下面我们就具体来介绍一下
Next-Key 锁 = 间隙锁(Gap Lock) + 行锁(Record Lock)

1. 行锁(Record Lock)
  • 作用:锁定表中实际存在的某一行数据,防止其他事务修改或删除这一行。
  • 示例:当事务 A 执行 SELECT * FROM stu WHERE id = 10 FOR UPDATE; 时,会对 id=10 的行加行锁,其他事务无法修改或删除 id=10 的记录。
2. 间隙锁(Gap Lock)
  • 作用:锁定不存在实际记录的“间隙区间”,防止其他事务在该区间内插入新记录(这是解决幻读的核心)。

  • 间隙的定义:表中相邻两条记录之间的区间,或第一条记录之前、最后一条记录之后的区间。
    例如,表中 id 存在 5、10、15 三条记录,则间隙包括:
    (-∞, 5)、(5, 10)、(10, 15)、(15, +∞)。

  • 示例:事务 A 执行 SELECT * FROM stu WHERE id BETWEEN 5 AND 15 FOR UPDATE; 时,除了对 id=5、10、15 加行锁,还会对间隙 (5,10)、(10,15) 加间隙锁,阻止其他事务在这些区间插入新记录(如 id=7、12 等)。

3. Next-Key 锁(组合效果)

Next-Key 锁是行锁与间隙锁的合并,它会锁定一个包含实际记录和前后间隙的连续区间。

  • 对于 id=10 这条记录,Next-Key 锁的范围是 (5, 10](左开右闭),既锁定 id=10 这一行,也锁定 5~10 之间的间隙。
  • 当执行范围查询(如 WHERE id > 8 AND id < 12)时,Next-Key 锁会覆盖整个查询范围,阻止区间内的修改和插入。
Next-Key 锁如何解决幻读?

以具体案例说明:
假设 stu 表中 id 为 5、10、15,事务 A 和 B 操作如下:

  1. 事务 A(RR 级别):

    START TRANSACTION;
    -- 查询并锁定 score > 80 的记录(假设对应 id=10、15)
    SELECT * FROM stu WHERE score > 80 FOR UPDATE;
    
    • InnoDB 会对 id=10、15 加行锁;
    • 同时对 score > 80 对应的间隙(如 (10,15)、(15, +∞))加间隙锁。
  2. 事务 B:

    -- 尝试插入一条 score=85 的新记录(id=12,属于事务 A 锁定的间隙)
    INSERT INTO stu (id, score) VALUES (12, 85);
    
    • 由于 id=12 落在事务 A 锁定的间隙 (10,15) 中,事务 B 会被阻塞,等待事务 A 释放锁。
  3. 事务 A 继续执行:

    -- 再次查询,结果与第一次一致(无新增记录)
    SELECT * FROM stu WHERE score > 80;
    COMMIT; -- 释放所有锁,事务 B 此时才能执行插入
    

通过阻止事务 B 插入符合条件的新记录,事务 A 在整个事务中始终看到一致的结果集,从而解决了幻读。

Next-Key 锁使用注意事项
  1. Next-Key 锁仅在 RR 级别生效:Next-Key 锁是 InnoDB 在 RR 级别下的特有机制,读已提交(RC)级别会禁用间隙锁(仅用行锁),因此 RC 级别可能出现幻读。
  2. Next-Key 锁通过索引锁定某个左开右闭区间:间隙锁基于索引生效,若查询未使用索引(全表扫描),会锁定整个表的所有间隙,导致并发性能下降。
  3. Next-Key 锁通过范围查询触发:通常在使用 SELECT ... FOR UPDATE(写锁)或 SELECT ... LOCK IN SHARE MODE(读锁)的范围查询时触发,普通 SELECT(快照读)不会加锁,但依赖一致性快照避免幻读。

4.串行化【serializable】

什么是串行化?

就是对所有操作都加锁,将并发的多进程/线程彻底串行化
但是效率非常低很低,几乎完全不会被采用

串行化的隔离条件下,两个事务访问同一张表的表现

串行化如何控制表访问?

在串行化的隔离条件下,当多事务同时访问同一张表时,第一个访问的事务要给这张表上一把共享锁(S 锁,允许共享读,但不允许写),上了之后如果有其他事务想要修改这个表,那他就会陷入阻塞,直到这个读锁被释放。同样地,当事务想要通过INSERT/UPDATE/DELETE语句修改这张表,或者通过SELECT … FOR UPDATE 对表进行加锁读操作时,就会给这张表上一把排他锁(X 锁)。上锁之后,其余事务再想修改或者加锁读,就会陷入阻塞,直到X锁释放为止。

那上面一段中说的S锁和X锁,都是什么时候才会释放呢?这些锁的生命周期会不会受不同的隔离级别影响呢?

无论是 X 锁还是 S 锁,只要是 “事务主动或隐式获取” 的锁,其持有周期完全跟随事务 —— 从锁被获取(语句执行时)到事务结束(提交 / 回滚),锁才会释放。不管是什么隔离级别,都是一样的

除了串行化之外,其他的隔离级别还会用到X锁与S锁吗

除了串行化隔离级别,其他隔离级别(如 读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read))也会频繁用到 X锁(排他锁) 和 S锁(共享锁)——核心区别在于“是否主动/隐式加锁”,而非“是否使用锁”。X锁和S锁是数据库实现并发控制的基础机制,所有隔离级别(包括非串行化)在处理“修改操作”或“显式加锁读”时,都会依赖这两种锁。

(1)各隔离级别对X锁的使用:完全一致(必用)

X锁用于保障“修改操作的原子性”(防止同一行数据被多个事务同时修改),所有隔离级别下,只要执行修改操作(UPDATE/DELETE/INSERT),或显式加锁读(SELECT ... FOR UPDATE),都会为目标数据加X锁,且锁的生命周期均为“事务结束(提交/回滚)释放”,与隔离级别无关。

隔离级别触发X锁的典型操作锁的核心作用
读未提交(RU)UPDATE user SET age=20 WHERE id=1阻止其他事务同时修改id=1的行,避免“脏写”(即使RU允许读未提交数据,也禁止脏写)。
读已提交(RC)DELETE FROM user WHERE id=2确保删除操作的原子性,其他事务需等待锁释放后才能修改/删除id=2的行。
可重复读(RR)SELECT balance FROM user WHERE id=3 FOR UPDATE显式加X锁,后续事务无法加S锁/X锁,保障当前事务对id=3的行有“独占修改权”。
串行化(SERIALIZABLE)INSERT INTO order (user_id) VALUES (4)对插入的新行加X锁,防止其他事务修改该新行(与其他级别逻辑一致)。

结论:X锁是“修改操作的标配”,所有隔离级别都必须依赖X锁防止“脏写”,使用逻辑完全一致。

(2)各隔离级别对S锁的使用:差异在“是否隐式加锁”

S锁用于保障“读操作的一致性”(多个事务可同时读,但禁止写),不同隔离级别对S锁的使用差异,体现在“普通SELECT是否隐式加S锁”——仅串行化级别会对普通SELECT隐式加S锁,其他级别需“显式声明”才会加S锁,但所有级别都支持通过显式语法加S锁。

  1. 非串行化级别:仅“显式加锁读”才会用S锁
    读未提交(RU)、读已提交(RC)、可重复读(RR)这三个级别,普通SELECT默认是“无锁快照读”(依赖MVCC机制实现),不会主动加S锁;但如果通过显式语法声明“加共享锁读”,则会为目标数据加S锁,且锁生命周期仍为“事务结束释放”。
隔离级别是否为普通SELECT加S锁触发S锁的典型操作(显式)锁的核心作用
读未提交(RU)否(快照读)SELECT name FROM user WHERE id=1 FOR SHARE允许其他事务加S锁(共同读),但禁止加X锁(修改),避免读时被修改。
读已提交(RC)否(快照读)SELECT age FROM user WHERE id=2 LOCK IN SHARE MODE(MySQL语法)确保当前事务读的是“已加锁的一致性数据”,其他事务修改需等待S锁释放。
可重复读(RR)否(快照读)SELECT balance FROM user WHERE id=3 FOR SHARE结合RR的MVCC,既保证“可重复读”,又通过S锁阻止其他事务修改,避免“不可重复读”。
串行化(SERIALIZABLE)是(隐式加锁)普通SELECT * FROM user WHERE id=4对所有普通读隐式加S锁,强制“读-写”串行化,彻底避免不可重复读和幻读。
  1. 关键差异:为何非串行化级别不隐式加S锁?
    为了平衡“一致性”和“并发性能”:
  • 串行化级别通过“隐式加S锁”强制读-写串行,保障最高一致性,但会降低并发(读会阻塞写,写也会阻塞读);
  • 非串行化级别(尤其是RC、RR)通过“MVCC快照读”替代“隐式S锁”——普通读无需加锁,直接读取版本化的快照数据,既避免了锁竞争,又能满足当前隔离级别的一致性需求(如RC避免脏读,RR避免不可重复读)。
  • 只有当用户明确需要“读锁保护”(如“读后立即写,防止中间被修改”)时,才通过FOR SHARE显式加S锁,按需平衡一致性和性能。

(3)总结:各隔离级别与X/S锁的关系

锁类型读未提交(RU)读已提交(RC)可重复读(RR)串行化(SERIALIZABLE)核心规律
X锁用(修改/显式加锁读)用(修改/显式加锁读)用(修改/显式加锁读)用(修改/显式加锁读)所有级别必用,用于防止脏写,释放时机均为事务结束。
S锁仅显式加锁读用仅显式加锁读用仅显式加锁读用显式加锁读+普通读隐式用差异在“普通读是否隐式加锁”,显式加锁读的逻辑所有级别一致,释放时机均为事务结束。

简言之:X锁是“修改操作的基础”,所有隔离级别都离不开;S锁是“读一致性的工具”,非串行化级别按需显式使用,串行化级别强制隐式使用——但无论哪种情况,X锁和S锁的核心机制(加锁逻辑、释放时机)在所有隔离级别下都是统一的。

实际案例:两个事务访问同一张表的表现

假设存在 stu 表,事务 A 和事务 B 分别在两个 MySQL 客户端中执行操作,隔离级别均为 串行化:

案例 1:事务 A 先执行读操作,事务 B 后执行写操作

  1. 事务 A(客户端 1):

    SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- 设为串行化
    START TRANSACTION;
    SELECT * FROM stu; -- 普通读(非加锁)
    -- 此时事务 A 未提交,持有“一致性快照”
    
  2. 事务 B(客户端 2):

    SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    START TRANSACTION;
    INSERT INTO stu (name, age) VALUES ('张三', 20); -- 尝试写操作
    -- 结果:事务 B 被阻塞,终端显示“Waiting for table metadata lock”或“Waiting for row lock”
    
  3. 后续操作:

    • 若事务 A 执行 COMMIT;(提交),事务 B 的插入操作会立即执行;
    • 若事务 A 执行 ROLLBACK;(回滚),事务 B 的插入操作也会解除阻塞并执行。

案例 2:事务 A 先执行写操作,事务 B 后执行读操作

  1. 事务 A(客户端 1):

    SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    START TRANSACTION;
    INSERT INTO stu (name, age) VALUES ('李四', 22); -- 写操作,加行锁+间隙锁
    -- 未提交
    
  2. 事务 B(客户端 2):

    SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    START TRANSACTION;
    SELECT * FROM stu FOR UPDATE; -- 加锁读操作
    -- 结果:事务 B 被阻塞,等待事务 A 释放锁
    
  3. 后续操作:

    • 事务 A 提交后,事务 B 的查询会返回包含“李四”的完整结果;
    • 事务 A 回滚后,事务 B 的查询会返回不含“李四”的结果。
总结

在串行化隔离级别下,两个事务允许访问同一张表,但访问会被 InnoDB 的锁机制强制“串行化”:一个事务的操作未结束前,另一个事务的写操作或加锁读操作会被阻塞。这种机制确保了最高的隔离性,但仅适合并发量极低、对数据一致性要求极高的场景(如金融核心交易的对账逻辑),多数业务场景更倾向于使用默认的 RR 级别。

串行化的隔离性下,解决了哪些安全问题?还存在哪些安全问题?

在串行化的隔离性下,脏读问题、不可重复读问题和幻读问题都得到了解决,基本不存在安全问题了

MYSQL中锁的分类

在MySQL中,锁的“等级”(通常更准确的表述是锁的粒度和锁的作用范围)确实存在分层,但核心分类是 “锁粒度”(表级锁、行级锁)和 “锁的作用对象”(事务锁、元数据锁等),而非简单的“表级事务级”——“事务级”更偏向描述锁的“生命周期与事务绑定”,而非独立的锁等级。

下面从 锁粒度(核心分层)、锁作用范围(事务/元数据等)两个维度,结合MySQL的具体实现,系统梳理锁的分类体系:

核心分层:按“锁粒度”划分(表级锁 vs 行级锁)

锁粒度决定了“锁控制的范围大小”——粒度越大,并发性能越低(锁冲突概率高),但锁开销越小(管理简单);粒度越小,并发性能越高(锁冲突概率低),但锁开销越大(需管理更多锁实例)。MySQL同时支持这两种粒度,不同存储引擎(如InnoDB、MyISAM)对锁的支持不同(MyISAM仅支持表级锁,InnoDB同时支持表级锁和行级锁)。

1. 表级锁(Table-Level Lock)
  • 定义:锁定整个表,对表中所有行的操作都会受影响。

  • 特点:开销小、加锁快、无死锁风险,但锁冲突概率极高(如一个事务锁表后,其他事务无法修改表中任何行),并发性能差。

  • MySQL支持的表级锁类型:

    • 表级共享锁(Table Shared Lock, TS):允许持有锁的事务读表,禁止写表;多个事务可同时持有TS锁(读不互斥)。
      示例:LOCK TABLES user READ;(显式加表级S锁,事务结束或执行UNLOCK TABLES释放)。
    • 表级排他锁(Table Exclusive Lock, TX):允许持有锁的事务读写表,禁止其他事务读/写表(读写都互斥)。
      示例:LOCK TABLES user WRITE;(显式加表级X锁,释放时机同上)。
    • 意向锁(Intention Lock):InnoDB特有的“表级辅助锁”,用于“提前声明事务的加锁意图”,避免表级锁与行级锁的冲突。
      • 意向共享锁(IS):事务计划对表中某些行加行级S锁前,先加IS锁(表级);
      • 意向排他锁(IX):事务计划对表中某些行加行级X锁前,先加IX锁(表级)。
        意向锁仅用于“锁冲突判断”,不会阻塞普通的读/写操作(例如,IS锁与其他表级IS/IX锁兼容,仅与TX锁冲突)。
  • 典型场景:MyISAM引擎的所有写操作(UPDATE/DELETE)默认加表级X锁;InnoDB在执行ALTER TABLE(修改表结构)、LOCK TABLES(显式锁表)时会加表级锁。

2. 行级锁(Row-Level Lock)
  • 定义:仅锁定表中“满足条件的行”,未锁定的行仍可被其他事务读写。

  • 特点:开销大、加锁慢、可能产生死锁(多个事务互相等待对方的行锁),但锁冲突概率极低,并发性能极高——是InnoDB支持高并发的核心基础。

  • MySQL(InnoDB)支持的行级锁类型:

    • 行级共享锁(Row Shared Lock, RS):即之前提到的 S锁,允许持有锁的事务读该行,禁止其他事务加X锁(可加S锁)。
      触发方式:SELECT ... FOR SHARE(或LOCK IN SHARE MODE,MySQL语法)。
    • 行级排他锁(Row Exclusive Lock, RX):即之前提到的 X锁,允许持有锁的事务读写该行,禁止其他事务加S锁/X锁(完全互斥)。
      触发方式:UPDATE/DELETE/INSERT(隐式加锁)、SELECT ... FOR UPDATE(显式加锁)。
    • 间隙锁(Gap Lock)与临键锁(Next-Key Lock):InnoDB在 可重复读(RR) 隔离级别下,为防止“幻读”引入的特殊行级锁(锁定“行之间的间隙”而非具体行):
      • 间隙锁:锁定“不存在的行范围”(如WHERE id BETWEEN 10 AND 20,若表中无id=15的行,会锁定10-20的间隙),阻止其他事务插入该范围的行;
      • 临键锁:间隙锁+行锁的组合(默认锁模式),既锁定行,也锁定行前后的间隙,彻底避免幻读。
  • 典型场景:InnoDB引擎的所有行修改/显式加锁读操作(如UPDATE user SET age=20 WHERE id=1),默认加行级X锁;SELECT ... FOR SHARE加行级S锁。

按“锁的作用范围”划分:事务锁 vs 元数据锁

除了“粒度”,还可按“锁保护的对象”划分,核心包括 事务锁(保护数据修改的原子性)和 元数据锁(保护表结构的一致性):

1. 事务锁(Transaction Lock)
  • 定义:与事务绑定的锁,生命周期为“事务开始→事务提交/回滚”,用于保障事务的ACID特性(尤其是原子性、隔离性)。
  • 包含的锁类型:
    • 所有行级锁(S锁、X锁、间隙锁、临键锁);
    • 表级锁中的“意向锁(IS/IX)”“显式表级S/X锁(LOCK TABLES)”。
  • 核心特点:仅在事务内生效,事务结束后自动释放,是处理“数据并发修改”的核心锁类型(之前讨论的X锁、S锁均属于此类)。
2. 元数据锁(Metadata Lock, MDL)
  • 定义:保护“表结构元数据”(如表名、列名、索引结构)的锁,与事务无关,用于避免“表结构修改”与“数据读写”的冲突。
  • 触发场景:
    • 当执行SELECT/INSERT/UPDATE/DELETE等“数据操作”时,MySQL会自动加 MDL读锁(多个事务可同时加,不互斥);
    • 当执行ALTER TABLE/DROP TABLE/RENAME TABLE等“表结构修改操作”时,MySQL会自动加 MDL写锁(仅允许一个事务加,与读锁、写锁都互斥)。
  • 核心特点:
    • 无需显式声明,MySQL自动管理;
    • MDL读锁会阻塞MDL写锁(例如,若有事务正在执行SELECT,则ALTER TABLE会被阻塞,直到所有SELECT结束);
    • MDL写锁会阻塞所有MDL读锁/写锁(例如,ALTER TABLE执行时,所有后续的SELECT都会被阻塞,直到ALTER TABLE结束)。
    • 生命周期:MDL读锁在“语句执行结束后释放”(非事务结束);MDL写锁在“表结构修改操作完成后释放”。
MySQL锁的分类体系总结

为了更清晰地理解,用表格梳理核心分类维度:

划分维度具体锁类型核心作用典型存储引擎支持
按锁粒度1.表级锁锁定整个表,开销小、并发低MyISAM(仅支持)、InnoDB
1.1表级S锁(TS)、表级X锁(TX)控制表级读写互斥
1.2 意向锁(IS/IX)辅助行级锁,避免表级锁冲突InnoDB特有
2.行级锁锁定单行/间隙,开销大、并发高InnoDB特有
2.1 行级S锁、行级X锁控制行级读写互斥
2.2 间隙锁、临键锁防止幻读(RR隔离级别)
按作用范围(1)事务锁保障事务ACID,与事务绑定InnoDB(核心)、MyISAM
(1-1) 行级S/X锁、意向锁、显式表级S/X锁保护数据修改一致性
(2)元数据锁(MDL)保护表结构元数据,与事务无关所有存储引擎(MySQL层)
(2-1) MDL读锁(数据操作触发)、MDL写锁(表结构修改触发)避免表结构与数据操作冲突
特别注意
  1. “事务级锁”不是独立等级:“事务级”描述的是“锁的生命周期与事务绑定”,而非“锁的粒度”——例如,行级S锁、表级意向锁都是“事务级锁”,但它们的粒度不同。
  2. InnoDB优先用行级锁:InnoDB虽然支持表级锁,但默认会优先使用行级锁(仅锁定修改的行),以提升并发性能;只有在无法用行级锁的场景(如ALTER TABLE)才会用表级锁。
  3. MyISAM无行级锁:MyISAM引擎仅支持表级锁,因此在高并发写场景下性能极差(一个写操作会锁整个表),目前已逐渐被InnoDB取代。

不同的隔离级别的安全问题

不同隔离级别分别能解决哪些安全问题?

其实不同的隔离级别,就是为了解决一个个的安全问题而递进设置的
比如最开始的读未提交,在这个隔离性下,存在着脏读、不可重复读还有幻读问题
为了解决脏读问题,我们对读未提交做了进一步的约束,不允许其他事务查看一个事务未提交时更新的数据,将隔离级别升级成了读提交。升级成读提交之后,虽然解决了脏读问题,但是依然存在着不可重复度和幻读的问题

为了解决不可重复读问题,我们对读提交做了进一步的约束,规定一个事务在运行过程中,只能访问事务开始时数据库的历史版本,不让事务看到在其运行过程中数据库的更新操作。由于隔离级别就进一步升级成了可重复读。可重复读的隔离级别下,脏读与不可重复读的问题都解决了,但是依然存在着幻读问题

为了解决幻读问题,我们又对可重复提交做了进一步的限制,只要两个事务访问,最终变成了可串行化。

我们一般事务默认的隔离级别是哪一级?

RR:可重复读

事务的一致性

对事物的隔离性有了初步了解之后,我们再来回头看一下事务的一致性

如何理解一致性中的一致?与之对应的不一致又如何理解呢?

事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。
为了实现一致性,防止改未完成的事务对数据库所做的修改已被写入数据库,我们就引入了回滚机制,用事务的原子性保证,如果事务最后没有执行完成,那么就会将数据库回滚到事务执行前的状态

事务的一致性是如何实现的?

其实一致性和用户的业务逻辑强相关,一般MySQL提供技术支持,但是一致性还是要用户业务逻辑做支撑
总结来说就是,技术上,通过AID(原子性、隔离性、持久性)支持一致性的实现,但最终一致性的实现,需要由用户的具体操作实现的

面试官:MySQL事务的隔离性是如何实现的? 并发场景 最近做了一些分布式事务的项目,对事务的隔离性有了更深的认识,后续写文章聊分布式事务。今天就复盘一下单机事务的隔离性是如何实现的? 隔离的本质就是控制并发,如果SQL语句就是串行执行的。那么数据库的四大特性中就不会有隔离性这个概念了,也就不会有脏读,不可重复读,幻读等各种问题了 对数据库的各种并发操作,只有如下四种,写写,读读,读写和写读 写-写 事务A更新一条记录的时候,事务B能同时更新同一条记录吗? 答案肯定是不能的,不然就会造成脏写问题,那如何避免脏写呢?答案就是加锁 读-读 MySQL读操. 阅读详情

相关推荐

python进行windows系统UI自动化之【pyautoit】

一般以我们平时操作,会从下图上方的地址栏进行操作,这里注意可以直接从下方的文件名处,输入对应的绝对地址,如:F:\程序设计书籍\《啊哈!pyautoit 是一个用python写的基于AutoItX3.dll的接口库,用来进行windows窗口的一系列操作,也支持鼠标键盘的操作。点击上访的图标,进行拖拉,到想访问的位置,注意下图两个红框中的数值,上面的框表示页面的标题和类,下面的框表示控件的类和序号(一般连起来使用)打开Auto Window Info(x64)或Auto Window Info(x86)

weixin_43936332的博客 9314

MySQL的隔离性测试

在阅读本文前,请思考以下分别输出什么 操作序列1 在数据库中存入 A=1 Client1启动一个事物T1 Client2启动一个事物T2 Client1 读取 A 的值 X1 Client2设置 A=2 Client2提交事物T2 Client1 读取 A 的值 X2 Client1提交事物T1 Client1 读取 A 的值 X3 请问 X1 X2 X3 分别为什么值? 操作序列2 在数据库中存入 A=1 Client1启动一个事物T1 Client2启动一个事物T2 Client2设置 A=2 C

I have a adream 433

【本体】Protege高效批量导入实例(Individuals)的自动化实践

本文详细介绍了在Protege中高效批量导入实例(Individuals)的自动化实践方法。通过分析Protege本体文件结构,提供Python脚本示例,帮助用户快速处理大规模数据导入,显著提升知识图谱构建效率。特别适合需要处理数千个实例的医疗、制药等领域应用。

weixin_30275415的博客 408

【MySQL】事务

【代码】【MySQL】事务。

weixin_60819724的博客 240

SAP FICO 银企直连

银企直联或者自动付款的目的是和银行做一个接口,把SAP中的到期应付款(也包括预付款)按照一定格式(银行要求的)在审批后发送给银行,请银行按照这个付款指定进行付款,并跟踪付款状态的过程,这个过程在SAP中如何实现呢?根据个人项目经验,客户需求可分为如下三种: 1. 第一种是完全不自动方式,仅批量生成付款凭证,实际的付款还是通过原来的流程执行,和银行没有任何接口; 2. 第二种是半自动方式,这种方式下需要按照银行的要求的格式生成付款条件,然后把付款文件下载下来,通过企业版的网银接口把付款文件进行上载,提交后

IamRunjiang的博客 9289

1小时读完100篇文献的正确打开方式

各位同仁好,我是七哥。一个在高校里从事人工智能 相关领域研究,钻研用大模型AI实操的学术人。可以和七哥交流学术写作或Gemini、GPT、Claude 等大模型 学术实操相关问题,多多交流,相互成就,共同进步。文献阅读与整理一般都是最先开始、却也最容易被低估的一步。很多学术同仁一开始就陷入越读越多、越读越乱的状态:论文下载了一大堆,但真正能用来支撑自己观点的内容却始终难以提炼出来。一方面,我们需要通过文献了解该研究领域的整体发展脉络,把握当前学界已经讨论到什么程度;

智能AI让学术科研更容易 48

【MySQL】事务(隔离性、MVCC)

事务的概念以及原理

weixin_69380220的博客 1776

【目标检测】基于yolov5的道路坑洼检测(附代码和数据集)

基于yolov5的道路坑洼检测(附代码和数据集)

学无止境、积少成多、厚积薄发 4620

【MySQL】事务及隔离性

【MySQL】事务及隔离性

Sweet_0115的博客 1445

环境仿真软件:MIKE 21_(9).MIKE21水生植物模块介绍

MIKE21支持多种水生植物的模拟,用户需要在配置文件中定义植物种类及其特性。</</</</</</</</</假设我们需要定义一种新的水生植物“水葫芦”(Water Hyacinth),并将其特性写入配置文件。# 创建XML根元素# 定义新的植物种类# 生成XML文件假设我们需要分析仿真的水流速度变化,并绘制水流速度随时间变化的图。# 读取NetCDF文件# 获取水流速度数据# 获取时间数据# 绘制水流速度随时间变化的图plt.xlabel('时间 (天)')

kkchenjj的博客 727

静态时序分析(STA)—— 标准单元库

目录 1、时序库 概览 2、时序模型 1、基本概念 2、影响因素 3、线性延时模型 4、非线性延时模型 5、单元时序弧 1、组合逻辑单元 2、时序逻辑单元 6、线负载模型 参考说明 上一篇,学习了 STA相关的基本概念,本篇继续学习 STA相关的 标准单元库。 1、时序库 概览 库文件概览: 2、时序模型 1、基本概念 2、影响因素 对于组合逻辑的时序弧而言,其延时的大小取决于: 1、输出负载,即,输出端的电容负载的大小。容性负载越大,...

记录所学,分享知识,结识挚友 2852

【MySQL】事务及其隔离性/隔离级别

MySQL事务的隔离级别(只有innoDB解决了RR级别的幻读问题)

学了就忘是正常现象 5475

dolphinscheduler服务注册中心源码解析(一)服务注册与发现整体设计

下一篇文章我们开始讲解dolphinscheduler基于Zookeeper实现注册中心的源码解析。

最爱嫣夜来 375

跟面试官侃半小时MySQL事务隔离性,从基本概念深入到实现

来源 |阿丸笔记提到MySQL的事务,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关。而事务的ACID(即原子性Atomi...

优快云云计算 4万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

【MySQL】——事务的隔离性

在上篇事务一文中,我们提到了事务的四个属性 原子性、持久性、隔离性、一致性。原子性和持久性我们已经在上篇文章中见识到了,但是隔离性和一致性又该怎么理解呢?我们首先来看事务的隔离性,隔离性。同时,隔离级别。其中隔离级别越严格,安全性越高,但数据库的并发性能也就越低,往往需要在两者之间找一个衡点。不可重复读的重点是修改和删除:同样的条件, 你读取过的数据,再次读取出来发现值不一样了幻读的重点在于新增:同样的条件, 第1次和第2次读出来的记录数不一样。

学习日记 1155

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

MySQL 事务四大特性和事务隔离级别

MySQL 事务具有四个特性:原子性、一致性、隔离性、持久性,这四个特性简称 ACID 特性一、原子性(Atomicity ):一个事务是一个不可再分割的整体,要么全部成功,要么全部失败事务在数据库中就是一个基本的工作单位,事务中包含的逻辑操作(SQL 语句),只有两种情况:成功和失败。事务的原子性其实指的就是这个逻辑操作过程具有原子性,不会出现有的逻辑操作成功,有的逻辑操作失败这种情况二、一致性(Consistency ):一个事务可以让数据从一种一致状态切换到另一种一致性状态举例说明:张三给李四转账 1

辰风沐阳 1万+

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

mysql数据库的事务 mysql事务的四大特征 mysql事务的隔离性 事务隔离性的等级

mysql的事务我们在说mysql数据的隔离性之前,就先要了解mysql的事务,用简单的话来说,就是完成对数据表完成一系列增删减的单元操作,在事务的范围之内,要么每条指令都执行,要么全都不执行。或许,这句话并不严谨,但这是个人的理解。mysql事务的四大特征(ACID)原子性(Atomicity)一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事...

念兮为美 3075

MySQL事务以及隔离性

MySQL事务以及隔离性, 事务ACID特性

q160336802的博客 1333

Mysql事务隔离性的原理分析

换言之,提高了效率。Read View就是事务进行 快照读 操作的时候生产的 读视图 (Read View),在该事务执行的快照读的那一刻,会生成数 据库系统当前的一个快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增 的,所以最新的事务,ID值越大)。如果记录的DB_TRX_ID 值小于 Read View 中的 m_up_limit_id 值,表示这个版本的记录是在创建 Read View 前已经提交的事务生成的,所以该版本的记录对当前事务可见。

cjforever14的博客 1636

事务的隔离性

事务的四大特性: ⑴ 原子性(Atomicity)   原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。 ⑵ 一致性(Consistency)   一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。 拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,

m0_47621042的博客 4184

mysql深入浅出之事务/隔离性

1. 事务 你要给朋友小王转100块钱,而此时你的银行卡只有100块钱。 转账过程具体到程序里会有一系列的操作,比如查询余额、做加减法、更新余额等,这些操作必须保证是一体的,不然等程序查完之后,还没做减法之前,你这100块钱,完全可以借着这个时间差再查一次,然后再给另外一个朋友转账,如果银行这么整,不就乱了么?这时就要用到“事务”这个概念了。 简单来说,事务就是要保证一组数据库操作,要么全部成功,要么全部失败。在MySQL中,事务支持是在引擎层实现的。你现在知道,MySQL是一个支持多引擎的系统,但并不是所

406156440的博客 2200

【MySQL事务】事务的隔离级别

正在进行中且尚未提交。

2301_80224556的博客 2120

MySQL中如何保证事务的隔离性,一致性

在MySQL中,通过设置合适的事务隔离级别、使用锁机制和MVCC、多种日志机制(如redo log和undo log)、数据库约束以及事务的ACID属性来保证事务的隔离性和一致性。根据应用的需求,选择合适的事务隔离级别和管理策略,可以在性能和数据一致性之间取得良好的平衡。

lssffy的博客 1249
上一篇: MYSQL 认识事务
下一篇: MYSQL 事务的隔离性(2)
烧冻鸡翅QAQ
博客等级 码龄6年 196粉丝 98原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值