主要内容:

  • 事务
  • 事务实例

1. 事务

1.1 事务简介

事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消

1.2 事务的特性

事务具有四个特征:

  • 原子性( Atomicity ) :表示组成一个事务的多个数据库操作是一个不可分隔的原子单元,只有所有的操作执行成功,整个事务才提交事务中任何一个数据库操作失败,已经执行的任何操作都必须撤销,让数据库返回到初始状态。
  • 一致性( Consistency ):事务操作成功后,数据库所处的状态和它的业务规则是一致的,即数据不会被破坏。
  • 隔离性( Isolation ):在并发数据操作时,不同的事务拥有各自数据空间,它们的操作不会对对方产生干扰。数据库规定了多种事务隔  离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性越好,但并发性越弱。
  • 持续性( Durability) :一旦事务提交成功后,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证能够通过某种机制恢复数据。

2. 锁

2.1 锁简介

数据库中的锁是指一种软件机制,用来控制防止某个用户(进程会话)在已经占用了某种数据资源时,其他用户做出影响本用户数据操作或导致数据非完整性和非一致性问题发生的手段

2.2 锁的划分

(1)根据锁的级别划分可以划分为共享锁,排它锁

  • 共享锁:针对同一条数据,多个读操作可以同时进行而不会互相影响.共享锁只针对update时候加锁,在未对update操作提交之前,其他事务只能获取最新的记录但不能够update操作
  • 排它锁:当前的写操作没有完成前,阻断其他的写锁和读锁

(2)根据锁的粒度划分

  • 行锁: 开销大,加锁慢,会出现死锁,锁定力度最小,发生锁冲突的概率最低,并发度高。
  • 表所: 开销小,加锁快,不会出现死锁,锁定力度大,发生冲突所的概率高,并发度低
  • 页面锁: 开销和加锁时间介于表锁和行锁之间,会出现死锁,锁定力度介于表和行行级锁之间,并发度一般

2.3 表锁

(1) 表锁的概述

  • MyISAM存储引擎:为了保证数据的一致性,更改数据时,防止其他人更改数据,可以人工添加表级锁。可以使用命令对数据库的表枷锁,使用命令对数据库的表解锁。
  • 给表加锁的命令Lock Tables,给表解锁的命令Unlock Tables
  • MyISAM引擎在用户读数据自动加READ锁,更改数据自动加WRITE锁。使用lock Tables和Unlock Tables显式加锁和解锁

(2) 添加表 读锁

  • 在一个数据库中创建两张表:

    mysql> create table t1(-> id int,-> name char(20),-> age int-> )ENGINE=MyISAM;
    Query OK, 0 rows affected (0.16 sec)mysql> create table t2(-> id int,-> name char(20),-> age int-> )ENGINE=MyISAM;
    Query OK, 0 rows affected (0.35 sec)

  • 在t1中插入两条记录
    insert into t1 values(1, 'alex', 19);
    insert into t1 values(3, 'alex1',18);

  • 对t1 加锁
    mysql> lock tables t1 read;
    Query OK, 0 rows affected (0.00 sec)

  • 加锁后只可以查询已经加锁的表t1,查询没有加锁的表时候会报错,而且当进行更新操作时候也会报错
    mysql> select * from t1;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    |    1 | alex  |   19 |
    |    2 | alex2 |   18 |
    +------+-------+------+
    2 rows in set (0.00 sec)mysql> select * from t2;
    ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES
    mysql> update t1 set age=100 where id =1;
    ERROR 1099 (HY000): Table 't1' was locked with a READ lock and can't be updated

  • 另起一个会话,对已经加锁的表进行查询,成功,但是当要进行更新操作会holding 即出现锁等待
    mysql> use db20;
    Database changed
    mysql> select * from t1;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    |    1 | alex  |   19 |
    |    2 | alex2 |   18 |
    +------+-------+------+
    2 rows in set (0.00 sec)mysql> update t1 set age=100 where id =2;

  • 此时将t1解锁,另一个会话中的更新操作会成功
    # 会话一中
    mysql> unlock tables;
    Query OK, 0 rows affected (0.00 sec)

    mysql> update t1 set age=100 where id =2;
    Query OK, 1 row affected (13 min 22.04 sec)
    Rows matched: 1  Changed: 1  Warnings: 0

    另外一个会话的更新操作成功

  • 在会话1中再次锁定t1表,后面带local参数
    mysql> lock tables t1 read local;
    Query OK, 0 rows affected (0.00 sec)

    在会话2中插入一条数据

    mysql> insert into t1 values(3, 'alex2',17);
    Query OK, 1 row affected (0.00 sec)

    但是 在会话1中查询发现并没有插入记录

    mysql> select * from t1;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    |    1 | alex  |   19 |
    |    2 | alex2 |  100 |
    +------+-------+------+
    2 rows in set (0.00 sec)

(3) 设置表锁的并发性

  • READ锁是共享锁,不影响其他会话的读取,但不能更新已经加READ锁的数据。
  • MyISAM表的读写是串行的,但是总体而言的,在一定条件下,MyISAM表也支持查询和插入操作的并发进行

注: MyISAM存储引擎有一个系统变量concurrent_insert,用以控制其并发插入的行为,其值分别可以为0、1或2。

  • 0:不允许并发操作
  • 1:如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录,是MySQL的默认设置。
  • 2:无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。
    在MySQL配置文件添加,concurrent_insert=2,重启mySQL服务设置生效。

2.4 行锁

(1) 行锁简介

  • InnoDB存储引擎实现的是基于多版本的并发控制协议——MVCC (Multi-Version Concurrency Control)。
  • MVCC的优点是读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能

在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)

  • 快照度: 读取的是记录的可见版本 (有可能是历史版本),不用加锁。
  • 当前读: 读取的是记录的最新版本,并且当前读返回的记录都会加上锁,保证其他事务不会再并发修改。事务加锁,是针对所操作的行,对其他行不进行加锁处理。

基于不同对的sql语句对读操作分类

  • 快照读: 简单的select 操作,属于快照读,不加锁

    select * from table where ?;

  • 当前读: 特殊的读操作,insert,update,delete,属于当前读,需要加锁
    select * from table where ? lock in share mode;
    select * from table where ? for update;
    insert into table values (…);
    update table set ? where ?;
    delete from table where ?;

    以上sql操作属于当前读,读取记录的最新版本,并且读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中,除了第一条语句,对读取记录加S锁 (共享锁)外,其他的操作,都加的是X锁 (排它锁)。

(2) 验证快照读

  • 打开会话1 创建表和数据

    mysql> create table t3(-> id int,-> name char(20),-> age int-> )ENGINE=innoDB;
    Query OK, 0 rows affected (0.60 sec)mysql> insert into t1 values(1, 'jerry', 19);
    Query OK, 1 row affected (0.00 sec)mysql> insert into t1 values(2, 'tom',18);
    Query OK, 1 row affected (0.00 sec)

    在会话1中开启事务,并查询 id =1 的数据

    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)mysql> select * from t3 where id=1;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    |    1 | jerry |   19 |
    +------+-------+------+
    1 row in set (0.00 sec)

  • 在会话2中更新id =1 的age为100,并查询数据内容
    mysql> update t3 set age=100 where id =1;
    Query OK, 1 row affected (0.36 sec)
    Rows matched: 1  Changed: 1  Warnings: 0mysql> select * from t3 where id =1;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    |    1 | jerry |  100 |
    +------+-------+------+
    1 row in set (0.00 sec)

  • 在会话1中查看id为1的数据信息
    mysql> select * from t3 where id=1;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    |    1 | jerry |   19 |
    +------+-------+------+
    1 row in set (0.00 sec)

    但是当会话1中提交事务后 再次查询时候此时数据已进行了更改

    mysql> commit-> ;
    Query OK, 0 rows affected (0.00 sec)mysql> select * from t3 where id=1;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    |    1 | jerry |  100 |
    +------+-------+------+
    1 row in set (0.00 sec)

(3) 验证当前读

  • 会话1开启事务,并且给select语句添加共享锁。

    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    mysql> select * from t3 where id =1 lock in share mode;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    |    1 | jerry |  100 |
    +------+-------+------+
    1 row in set (0.00 sec)

  • 在会话2中更新id = 1 的数据,此时会进入锁等待
    mysql> update t3 set age=66 where id =1;

  • 当会话1提交事务后,会话2的更新操作成功
    mysql> commit-> ;
    Query OK, 0 rows affected (0.00 sec)

    mysql> update t3 set age=66 where id =1;
    Query OK, 1 row affected (11.54 sec)
    Rows matched: 1  Changed: 1  Warnings: 0

(4) 验证事务给记录加锁

  • 会话1 开启事务, 在会话1中更新 id = 1 的数据

    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)mysql> update t3 set age=300 where id=1;
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1  Changed: 1  Warnings: 0

  • 在会话2 开启事务 ,更新id为2 的数据 ,此时会进入锁等待
    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)mysql> update t3 set age=200 where id=2;

    由于 t3 表没有指定主键,事务不支持行级锁。会话1的事务给整张表加了锁

  • 在会话1提交事务,此时会话2的修改成功  ,在会话2提交事务,解除对表的锁定
  • 在会话1 给表的 id增加主键 
    mysql> alter table t3 add primary key(id);
    Query OK, 0 rows affected (0.59 sec)
    Records: 0  Duplicates: 0  Warnings: 0

    在会话1 开启事务,并且更新id 为1 的数据

    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)mysql> update t3 set age=300 where id=1;
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1  Changed: 1  Warnings: 0

  • 在会话2上开启事务,并修改id为2的的数据,更新成功  ,说明会话1只锁定了ID为1的行
    mysql> update t3 set age=400 where id=2;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings:

    但是在会话2 中更新id = 1 的值,出现了等待,因为会话1给ID为1的行添加了独占锁

    mysql> update t3 set age=700 where id=1;

  • 当在会话1和会话2 中都提交事务后,会话1和和会话2 的修改都生效

(5)死锁的产生

A事务添加共享锁后,B事务也可以添加共享锁。A事务update锁定记录,处于等待中,于此同时B事务也update更新锁定的记录,就产生死锁。

  • 会话1 开启事务,查询id=1 的数据,并添加共享锁

    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)mysql> select * from t3 where id =1 lock in share mode;
    +----+-------+------+
    | id | name  | age  |
    +----+-------+------+
    |  1 | jerry |  700 |
    +----+-------+------+
    1 row in set (0.00 sec)

  • 同样,在会话2中 开启事务,查询id=1 的数据,并添加共享锁
    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)mysql> select * from t3 where id =1 lock in share mode;
    +----+-------+------+
    | id | name  | age  |
    +----+-------+------+
    |  1 | jerry |  700 |
    +----+-------+------+
    1 row in set (0.00 sec)

  • 在会话1 中更新 id=1 的数据,等待会话2释放共享锁
    mysql> update t3 set age =199 where id =1;

  • 在会话2更新ID为1的age为,会话2发现死锁,回滚事务。
    mysql> update t3 set age =199 where id =1;

  • 会话1 提交事务
    commit

3. 事务实例

3.1 由错误决定事务提交还是回滚

3.2 由自定义事件决定事务提交还是回滚

------  文章出处 https://blog.51cto.com/9291927/2096680 ----------

转载于:https://www.cnblogs.com/wcx666/p/10564483.html

MySql - 事务 | 锁相关推荐

  1. 一文读懂MySQL事务锁、事务级别

    锁 性能分:乐观(比如使用version字段比对,无需等待).悲观(需要等待其他事务) 乐观锁,如它的名字那样,总是认为别人不会去修改,只有在提交更新的时候去检查数据的状态.通常是给数据增加一个字段来 ...

  2. mysql 事务 锁 并发

    连接管理器:    接受请求    创建线程    认证用户    建立安全连接 并发控制:    mbox:MDA C/S: 100        10分钟:            多版本并发控制: ...

  3. 【MySQL】深入浅出剖析mysql事务锁机制 - 笔记

    事务的基本概念 事务的特点(ACID) 快照:之前的某一个历史的状态(类比虚拟机的快照),用于实现原子性 隔离性:通过锁机制来实现 锁:共享锁,排它锁,独占锁,临键锁,间隙锁,自增锁,意向锁 持久性: ...

  4. mysql 事务 for update,mysql事务锁_详解mysql 锁表 for update

    摘要 腾兴网为您分享:详解mysql 锁表 for update,智慧农业,真还赚,悦读小说,学习帮等软件知识,以及电池管家,三国群英传3,userland,运满满货主版,王者荣耀,简单3d动画,嘉丽 ...

  5. mysql事务锁导致tomcat崩溃_数据库连接池连接耗尽,导致tomcat请求无响应,呈现出假死状态...

    最困难的事情就是认识自己! 个人网站 ,欢迎访问! 前言:最近,测试部门的同事找到我,说他们测试时,没一会就发现服务接口请求一直无响应,Tomcat跟死掉了一样,也没有返回任何的错误响应,说让我赶紧排 ...

  6. jsp mysql事务锁_学生会事务管理系统的设计与实现(JSP,MySQL)(含录像)

    学生会事务管理系统的设计与实现(,MySQL)(含录像)(毕业论文15000字,程序代码,MySQL数据库) 系统功能分析 学生用户功能 1) 这就是本系统的学生用户功能框图(如图3-5所示).学生用 ...

  7. Mysql 事务锁表,解决方法

    2019独角兽企业重金招聘Python工程师标准>>> 1.执行 select * from information_schema.innodb_trx; kill 进程id 转载于 ...

  8. jsp mysql事务锁,JSP操作数据库的事务回滚

    基础介绍 1.先设置为手动提交 conn.setAutoCommit(false); //将自动提交设置为false 2.若成功则提交 conn.commit(); //当操作成功后手动提交 3.若失 ...

  9. 一图缕清 mysql 事务锁

  10. Mysql 事务中Update 会锁表吗?

    Mysql 事务中Update 会锁表吗? 两种情况: 1.带索引 2.不带索引 前提介绍: 方式:采用命令行的方式来模拟 1.mysq由于默认是开启自动提交事务,所以首先得查看自己当前的数据库是否开 ...

最新文章

  1. R语言生存分析(survival analysis)与生存资料有关的概念详解
  2. *HDU 2108 计算几何
  3. 密码统计分析工具pipal
  4. 网友收集了三年的最好的设计网站
  5. linux最简单搭建邮件服务器
  6. Linux安装或升级openssh步骤和可能遇到的问题
  7. Upload-Labs(17-20)
  8. 开源 serverless 产品原理剖析 - Kubeless 1
  9. Gtk实现GUI键盘并终端显示
  10. Android开发笔记(六十一)文件下载管理DownloadManager
  11. dw2019连接mysql数据库_Python3连接MySQL数据库
  12. 虚拟机 网卡模式配置
  13. mysql常见笔试_mysql常见笔试题
  14. 易网云授权php,网易云音乐热评api php源码
  15. 蚂蚁市场教程:电视安装看B站(哔哩哔哩)TV版
  16. 基于cesium的三维管线系统综述
  17. vlog拍摄与剪辑入门之路
  18. 加密货币是货币,而非股权
  19. jquery轮播插件
  20. ubuntu20.04禁止自动休眠的几种方式

热门文章

  1. mysql5.5默认引擎,在MySQL5.5以上系统中,默认的存储引擎是( )。
  2. BigInteger简单使用及方法总结
  3. Java 异常 (Exception) 剖析 与 用户自定义异常
  4. offline 与 online 事件监听浏览器是否在线
  5. Android 显式意图(Intent) 与 隐式意图
  6. 捷达vs7测试_没有大众车标的光环,捷达VS7显得更厚道,看看是不是你的菜
  7. 阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_2 Mybatis中编写dao实现类的使用-保存操作...
  8. 阶段3 1.Mybatis_05.使用Mybatis完成CRUD_1 回顾Mybatis的环境搭建-实现查询所有功能
  9. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_01 File类_7_File类创建删除功能的方法...
  10. 关于assert和de-assert的解释