【轻知识】mysql事务隔离笔记与练习

事务隔离级别

  • 读未提交(read uncommitted)
    读未提交是指,一个事务还没提交时,它做的变更就能被别的事务看到。
  • 读提交(read committed)
    读提交是指,一个事务提交之后,它做的变更才会被其他事务看到。
  • 可重复读(repeatable read)
    可重复读是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据
    是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的
  • 串行化(serializable)
    串行化,顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当
    出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

事务隔离级别练习

启动两个窗口

准备语句

create database mysql45;
use mysql45;

查看当前的事务隔离级别

mysql> show variables like 'tx_isolation'; # (我电脑是phpstudy自带的mysql版本是5.5。5.7引入了transaction_isolation,所以用show variables like 'transaction_isolation'; )或select @@tx_isolation;
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+

既然是 REPEATABLE-READ所以我先练习的是可重复读。

A表示左边窗口。B表示右边窗口。

读未提交

设置隔离级别的方式set tx_isolation = 'read-uncommitted';

B还没有commit事务的时候,A事务就能查出刚insert 的数据,也能查出update之后的数据。

当B commit之后,当然A查询的结果不变。

image.png

读提交

set tx_isolation = 'read-committed';

B未commit即便插入了数据或者更新元数据;A事务查询的结果是一致的。

B commit 之后;A事务查询到了B commit后的结果。

image.png

可重复读

set tx_isolation = 'repeatable-read';

B不commit即便插入了数据或者更新元数据;A事务查询的结果是一致的。(这点跟读提交是相同的)

B commit,A事务查询仍然是一致的。

image.png

串行化

set tx_isolation = 'serializable';

A 先操作语句,B会阻塞住。会用到锁。

image.png

或者B先操作语句会阻塞住A。

image.png

A commit之后,B不在阻塞就查到了提交的数据了。

image.png

begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作InnoDB 表的语句(第一个快照读语句),事务才真正启动。如果你想要马上启动一个事务,可以使用 start transaction with consistent snapshot 这个命令。
“start transaction with consistent snapshot; ”的意思是从这个语句开始,创建一个持续整个事务的一致性快照。所以,在读提交隔离级别下,这个用法就没意义了,等效于普通的 start transaction。

事务的启动方式

不同时刻启动的事务有不同的read-view,对同一条记录操作,会产生多个版本(回滚段),就是数据库的多版本并发控制(MVCC)。

select @@autocommit; # 或show variables like 'autocommit'; 我的默认为开启

  1. 显式启动事务语句, begin 或 start transaction。配套的提交语句是 commit,回滚语
    句是 rollback。
  2. set autocommit=0,这个命令会将这个线程的自动提交关掉。意味着如果你只执行一个 select 语句,这个事务就启动了,而且并不会自动提交。这个事务持续存在直到你主动执行 commit 或 rollback 语句,或者断开连接。

建议 autocommit 为1。通过显式语句启动事务。

长事务

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

除了对回滚段的影响,长事务还占用锁资源,可能拖垮整个库。

制造一个长事务。B窗口begin 执行一条语句。在A中查。

你可以在 information_schema 库的 innodb_trx 这个表中查询长事务。

select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60; // 大于60s。
image.png

我问了下DBA,他们监控的长事务就是这张表。

有次有一个小伙伴查数据,没提交就放着。

image.png

参考资料:

  • 《mysql45讲》03 事务隔离:为什么你改了我还看不见?(笔记来源)
  • 《mysql tx_isolation》https://blog.csdn.net/u012807459/article/details/52174601
  • 1~15讲 —丁奇大大,学习笔记 》https://blog.csdn.net/zxcc1314/article/details/84842650
  • 《MySQL · 源码分析 · InnoDB的read view,回滚段和purge过程简介》https://yq.aliyun.com/articles/560506

你可能感兴趣的:(【轻知识】mysql事务隔离笔记与练习)