美文网首页
MYSQL 事务以及锁(一)

MYSQL 事务以及锁(一)

作者: NealLemon | 来源:发表于2019-10-26 11:49 被阅读0次

学习笔记是学习了 极客时间 - 《MySQL实战45讲》整理的笔记。

事务隔离

事务的隔离性

  • 原子性
  • 一致性
  • 隔离性
  • 持久性

事务的隔离级别

  • 读未提交(read uncommitted):一个事务还没提交时,它做的变更就能被别的事务看到。

  • 读提交(read committed):一个事务提交之后,它做的变更才会被其他事务看到。(oracle默认事务,如果从oracle应用迁移到mysql,必须更改其事务级别)

    可重复读(repeatable read):一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据
    是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。(数据校对逻辑场景适用较多)

  • 串行化(serializable ):顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

MYSQL设置其隔离级别的参数是 transaction-isolation

mysql> show variables like 'transaction_isolation';
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
+-----------------------+----------------+

实例讲解

两个事务对同一条数据进行操作。

transaction1.png

根据不同的事务级别,得到的V1,V2,V3的结果也不同。

  • 读未提交:V1 的值就是 2。这时候事务 B 虽然还没有提交,但是结果已经被 A 看到了。因此,V2、V3 也都是 2。
  • 读提交: V1 是 1,V2 的值是 2。事务 B 的更新在提交后才能被 A看到。所以, V3 的值也是 2。
  • 可重复读:V1、V2 是 1,V3 是 2。之所以 V2 还是 1,遵循的就是这个要求:事务在执行期间看到的数据前后必须是一致的。
  • 串行化: 事务 B 执行“将 1 改成 2”的时候,会被锁住。直到事务 A 提交后,事务 B 才可以继续执行。所以从 A 的角度看, V1、V2 值是 1,V3 的值是 2。

内部逻辑

执行事务时,数据库会创建一个视图,访问的时候以视图的逻辑结果为准。

  • 可重复读:在事务启动时创建视图,整个事务存在期间都用这个视图。
  • 读提交:视图是在每个 SQL 语句开始执行的时候创建的。
  • 读未提交:直接返回记录上的最新值,没有视图。
  • 串行化:加锁的方式来避免并行访问。

隔离实现(回滚日志)

在 MySQL 中,实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。

多事务下的日志

假设一个值从 1 被按顺序改成了 2、3、4,在查询这条记录的时候,不同时刻启动的事务会有不同的 read-view,在回滚日志里面就会有类似下面的记录。

transaction2.png

如图中看到的,在视图 A、B、C 里面,这一个记录的值分别是 1、2、4,同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。对于 read-view A,要得到 1,就必须将当前值依次执行图中所有的回滚操作得到。

删除日志

当没有事务再需要用到这些回滚日志时(当系统里没有比这个回滚日志更早的 read-view 的时候),回滚日志会被删除。

长事务

避免长事务的几个基本配置

  • autocommit 参数: 建议设置为 1
    • set autocommit=0:这个命令会将这个线程的自动提交关掉。意味着如果你只执行一个 select 语句,这个事务就启动了,而且并不会自动提交。这个事务持续存在直到你主动执行 commit 或 rollback 语句,或者断开连接。
    • set autocommit=1: 通过显式语句的方式来启动事务。(begin 或 start transaction。配套的提交语句是 commit,回滚语句是 rollback。)
    • information_schema 库的 innodb_trx表中查询长事务。

MYSQL中的锁

全局锁

定义

MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令,之后的语句都会被阻塞(增删改操作,建表,修改表等)。

使用场景

全库逻辑备份

  • 非InnoDB引擎:全局锁后进行备份,(不建议使用set global readonly=true 方式来设置全库只读,global 变量的方式影响面太大,并且发生异常时,会一直保持只读状态)
  • 官方自带的逻辑备份工具是 mysqldump。当 mysqldump 使用参数–single-transaction
    的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。

表级锁

表锁

语法
lock tables … read/write
#lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。
#如果在某个线程 A 中执行 lock tables t1 read, t2 write; 这个语句,则其他线程写 t1、读写 t2 的语句都会被阻塞。同时,线程 A 在执行 unlock tables 之前,也只能执行读 t1、读写 t2 的操作。连写 t1 都不允许,自然也不能访问其他表。

可以用 unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。

元数据锁(MDL)

MDL 不需要显式使用,在访问一个表的时候会被自动加上。MDL 的作用是,保证读写的正确性。事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。

注意的问题

transaction3.png

尽管读锁不会阻塞,但是写锁之后的读锁,必须等待写锁释放后,才可以进行。

如果某个表上的查询语句频繁,而且客户端有重试机制,也就是说超时后会再起一个新session 再请求的话,这个库的线程很快就会爆满。

行锁(InnoDB引擎)

定义

行锁就是针对数据表中行记录的锁。这很好理解,比如事务 A 更新了一行,而这时候事务 B 也要更新同一行,则必须等事务 A 的操作完成后才能进行更新。

在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。

业务中的行锁优化

如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。

死锁和死锁检测

当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁。

举例

事务 A 在等待事务 B 释放 id=2 的行锁,而事务 B 在等待事务 A 释放 id=1 的行锁。 事务 A 和事务 B 在互相等待对方的资源释放,就是进入了死锁状态。

transaction4.png

两种解决策略

  • 超时设置:通过参数innodb_lock_wait_timeout 来设置(默认50S)。
  • 死锁检测:发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑。 死锁检测要耗费大量的 CPU 资源

相关文章

  • MYSQL 事务以及锁(一)

    学习笔记是学习了 极客时间 - 《MySQL实战45讲》整理的笔记。 事务隔离 事务的隔离性 原子性 一致性 隔...

  • 高性能Mysql笔记

    一、Mysql架构与历史 1、架构图 2、锁 表锁 行级锁 3、事务 死锁 Mysql中的事务 1

  • mysql锁以及事务隔离级别

    事务隔离级别 隔离级别脏读不可重复读幻读READ-UNCOMMITTED是是是READ-COMMITTED否是是R...

  • 淘宝MySQL文档整理

    MySQL · 引擎特性 · InnoDB 事务锁系统简介 MySQL · 引擎特性 · Innodb 锁子系统浅...

  • Mysql数据库

    MySQL知识图谱 MySQL索引 MySQL架构 MySQL锁 MySQL事务 MySQL集群 MySQL分库分...

  • 收藏-MySQL

    # MySQL的并发控制与加锁分析# MySQL的四种事务隔离级别# mysql共享锁与排他锁

  • mysql的锁+事务,联合的地方

    mysql的锁+事务,联合的地方 全文是对《Mysql 技术内幕 Innodb》中,锁和事务两个章节,自己能看懂或...

  • 数据库事务,锁

    事务 事务特点ACID 理解ACID 以银行转账为例 MySQL锁 锁是MySQL在服务器层和存储引擎层的并发控制...

  • Redis事务锁CAS实现以及深入误区

    Redis中的事务 Redis的事务没有mysql那么的丰富,但在JAVA web的开发过程中利用mysql事务锁...

  • mysql 锁以及事务等级分析

    先介绍ON DUPLICATE KEY UPDATE 插入时存在就更新,不存在就插入。应设置主键或者唯一索引情况下...

网友评论

    本文标题:MYSQL 事务以及锁(一)

    本文链接:https://www.haomeiwen.com/subject/ifvyvctx.html