死锁

死锁是指两个或多个事务在同一个资源上相互占用, 并请求锁定对方占用的资源, 从而导致恶性循环的现象. 当多个事务试图以不同顺序锁定资源时, 就可能产生死锁.
死锁发生以后, 只有部分或者完全回滚其中一个事务, 才能打破死锁.

MySQL 中的事务

在 MySQL 提供的众多存储引擎中, 只有 InnoDB 和 NDB Cluster 支持事务.

关于自动提交(AUTOCOMMIT)

MySQL 默认采用自动提交(AUTOCOMMIT) 模式. 即如果不显示地开始一个事务, 则每个操作都被当做一个事务执行提交操作.
我们可以通过

  1. SHOW VARIABLES LIKE 'autocommit';

查询当前是否已经开启了字段提交事务, 例如:

  1. mysql> SHOW VARIABLES LIKE 'autocommit';
  2. +---------------+-------+
  3. | Variable_name | Value |
  4. +---------------+-------+
  5. | autocommit | ON |
  6. +---------------+-------+
  7. 1 row in set (0.00 sec)

如果是 ON, 则表示已经开启了, 0 或 OFF 表示禁用.
可以通过 "set autocommit=0;" 来禁用自动提交:

  1. set autocommit=0;

对于非事务型存储引擎, 例如 MyISAM, 修改 AUTOCOMMIT 属性试不会有影响的.

自动提交和非自动提交的区别

下面以一个例子来展示 autocommit 启动和非启动时的区别.
首先建立一个测试用的表:

  1. CREATE TABLE `user` (
  2. `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  3. `name` VARCHAR(20) DEFAULT '',
  4. `age` INT(11) DEFAULT '0',
  5. PRIMARY KEY (`id`)
  6. )
  7. ENGINE = InnoDB
  8. DEFAULT CHARSET = utf8mb4

接着关闭自动提交功能:

  1. mysql> set autocommit=0;

然后插入一个数据:

  1. mysql> INSERT INTO user (`id`, `name`, `age`) VALUES (1, 'xys', 18);

接着查看数据:

  1. mysql> select * from user;
  2. +----+------+------+
  3. | id | name | age |
  4. +----+------+------+
  5. | 1 | xys | 18 |
  6. +----+------+------+
  7. 1 row in set (0.00 sec)

数据库中可以查询到这条数据了.
但是我们通过 SHOW BINLOG EVENTS 查看操作日志:

  1. mysql> show binlog events;
  2. +------------------+-----+----------------+-----------+-------------+---------------------------------------+
  3. | Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
  4. +------------------+-----+----------------+-----------+-------------+---------------------------------------+
  5. | mysql-bin.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.13-log, Binlog ver: 4 |
  6. | mysql-bin.000001 | 123 | Previous_gtids | 1 | 154 | |
  7. +------------------+-----+----------------+-----------+-------------+---------------------------------------+
  8. 2 rows in set (0.00 sec)

会发现上面的输出中, 并没有插入数据相关的记录, 并且此时如果我们退出 MySQL 的话, 那么我们插入的数据并没有被保存:

  1. mysql> exit
  2. Bye
  3. >>> mysql -u root -p
  4. Enter password:
  5. mysql> use test;
  6. Database changed
  7. mysql> select * from user;
  8. Empty set (0.00 sec)
  9. mysql>

如果我们不退出, 而是输入COMMIT; 时, 那么此时数据才真正保存到 MySQL 中:

  1. mysql> commit;
  2. Query OK, 0 rows affected (0.02 sec)
  3. mysql> show binlog events;
  4. +------------------+-----+----------------+-----------+-------------+---------------------------------------+
  5. | Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
  6. +------------------+-----+----------------+-----------+-------------+---------------------------------------+
  7. | mysql-bin.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.13-log, Binlog ver: 4 |
  8. | mysql-bin.000001 | 123 | Previous_gtids | 1 | 154 | |
  9. | mysql-bin.000001 | 154 | Anonymous_Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
  10. | mysql-bin.000001 | 219 | Query | 1 | 291 | BEGIN |
  11. | mysql-bin.000001 | 291 | Table_map | 1 | 342 | table_id: 108 (test.user) |
  12. | mysql-bin.000001 | 342 | Write_rows | 1 | 394 | table_id: 108 flags: STMT_END_F |
  13. | mysql-bin.000001 | 394 | Xid | 1 | 425 | COMMIT /* xid=58 */ |
  14. +------------------+-----+----------------+-----------+-------------+---------------------------------------+
  15. 7 rows in set (0.00 sec)

从上面的操作中我们可以看到, 当禁用了 AUTOCOMMIT 后, 我们对数据库的写入操作并不会实际落地到数据库中, 除非我们显示地提交事务.

接下来, 我们使能 AUTOCOMMIT, 再次进行相同的操作.

  1. mysql> set autocommit=1;
  2. mysql> SHOW VARIABLES LIKE 'autocommit';
  3. +---------------+-------+
  4. | Variable_name | Value |
  5. +---------------+-------+
  6. | autocommit | ON |
  7. +---------------+-------+
  8. 1 row in set (0.00 sec)

然后插入一个数据:

  1. mysql> INSERT INTO user (`id`, `name`, `age`) VALUES (1, 'xys', 18);

接着查看数据:

  1. mysql> select * from user;
  2. +----+------+------+
  3. | id | name | age |
  4. +----+------+------+
  5. | 1 | xys | 18 |
  6. +----+------+------+
  7. 1 row in set (0.00 sec)

数据库中可以查询到这条数据了.
我们再次查看 binlog, 对比一下和禁用 AUTOCOMMIT 时有什么差别:

  1. mysql> show binlog events;
  2. +------------------+-----+----------------+-----------+-------------+---------------------------------------+
  3. | Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
  4. +------------------+-----+----------------+-----------+-------------+---------------------------------------+
  5. | mysql-bin.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.13-log, Binlog ver: 4 |
  6. | mysql-bin.000001 | 123 | Previous_gtids | 1 | 154 | |
  7. | mysql-bin.000001 | 154 | Anonymous_Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
  8. | mysql-bin.000001 | 219 | Query | 1 | 291 | BEGIN |
  9. | mysql-bin.000001 | 291 | Table_map | 1 | 342 | table_id: 108 (test.user) |
  10. | mysql-bin.000001 | 342 | Write_rows | 1 | 394 | table_id: 108 flags: STMT_END_F |
  11. | mysql-bin.000001 | 394 | Xid | 1 | 425 | COMMIT /* xid=292 */ |
  12. +------------------+-----+----------------+-----------+-------------+---------------------------------------+
  13. 7 rows in set (0.00 sec)

我们看到, 和禁用 AUTOCOMMIT 不同的是, 使能 AUTOCOMMIT 时, 每个写操作都会进行事务的提交. 即上面的 insert 操作等效为:

  1. BEGIN;
  2. INSERT INTO user (`id`, `name`, `age`) VALUES (1, 'xys', 18);
  3. COMMIT;

004 --Mysql中的锁的问题的更多相关文章

  1. MySQL系列(五)---总结MySQL中的锁

    MySQL中的锁 目录 MySQL系列(一):基础知识大总结 MySQL系列(二):MySQL事务 MySQL系列(三):索引 MySQL系列(四):引擎 概述 MyISAM支持表锁,InnoDB支持 ...

  2. MySQL中InnoDB锁不住表的原因

    MySQL中InnoDB锁不住表是因为如下两个参数的设置: mysql> show variables like '%timeout%'; +-------------------------- ...

  3. MySQL中的锁、隔离等级和读场景

    一.导言 关于MySQL中的锁还有隔离等级这类话题,其概念性的解释早已泛滥.记住其概念,算不上什么.更重要的是思考:他们的区别和联系在哪儿,为什么会有这样的概念. 1)MySQL的锁(Lock)分为行 ...

  4. MySQL实战 | 06/07 简单说说MySQL中的锁

    原文链接:MySQL实战 | 06/07 简单说说MySQL中的锁 本文思维导图:https://mubu.com/doc/AOa-5t-IsG 锁是计算机协调多个进程或纯线程并发访问某一资源的机制. ...

  5. mysql中的锁表语句查看方法汇总

    mysql> show status like 'Table%'; +----------------------------+----------+ | Variable_name | Val ...

  6. 你了解MySQL中的锁吗?

    MySQL中的锁,分为全局锁.表级锁.行锁 全局锁 全局锁的意思就是,对整个数据库实例加锁,它的命令是FTWRL Flash tables with read lock 这个命令的语义是,使整个库处于 ...

  7. 谈谈MySQL中的锁

    谈谈MySQL中的锁 锁的定义 ​ 在生活中锁的例子就非常多了,所以应该很容易理解锁的含义.在计算机领域,可以这样来概述,锁是计算机协调多个进行进程并发访问某一资源的机制. ​ 在数据库中,锁也是一个 ...

  8. MySQL中的锁(表锁、行锁)

    锁是计算机协调多个进程或纯线程并发访问某一资源的机制.在数据库中,除传统的计算资源(CPU.RAM.I/O)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所在有数 ...

  9. mysql中的锁

    MYSQL不同的存储引擎支持不同的锁的机制 MyISAM 支持表锁,InnoDB支持表锁和行锁 表锁,行锁比较 表锁:开销小,加锁快:不会出现死锁:锁定力度大,发生锁冲突概率高,并发度最低 行锁:开销 ...

随机推荐

  1. 扯不清楚的virtual和abstract

    定义Person类: class Person { public void Say() { Console.WriteLine("I am a person"); } } 现在,我 ...

  2. 'vue-cli-service' 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    首先把 node_modules 文件夹删除 然后运行以下命令: cnpm install 这样就可以正常运行

  3. nodejs的expresss中post的req.body总是undefined的原因

    1)因为express将body-parser分离了出来,所以你需要手动添加进下面的内容即可 var path = require('path'); var bodyParser = require( ...

  4. 文件上传 python

    def upload(): r = requests.post( url='http://upload.renren.com/upload.fcgi?pagetype=addpublishersing ...

  5. 【jq】JQuery对select的操作

    下拉框 <select id="selectID" name="selectName"> <option vlaue="1" ...

  6. c++赋值运算符为什么要返回引用?

    为什么赋值运算符要返回引用?? 因为赋值操作会改变左值,而 + 之类的运算符不会改变操作数,所以说赋值运算符重载要返回引用以用于类似 (a=b)=c 这样的再次对a=b进行写操作的表达式.+ 返回一个 ...

  7. oracle 子查询 where having from ,from子查询提高效率

    where 子查询主要功能是控制数据行的,返回结果一般都是单行单列.多行单列.单行多列数据 单行单列 SELECT * FROM emp WHERE hiredate=( SELECT MIN(hir ...

  8. 1025 反转链表(链表,reverse)

    题目: 给定一个常数 K 以及一个单链表 L,请编写程序将 L 中每 K 个结点反转.例如:给定 L 为 1→2→3→4→5→6,K 为 3,则输出应该为 3→2→1→6→5→4:如果 K 为 4,则 ...

  9. 嵌入式C语言自我修养 02:Linux 内核驱动中的指定初始化

    2.1 什么是指定初始化 在标准 C 中,当我们定义并初始化一个数组时,常用方法如下: ] = {,,,,,,,,}; 按照这种固定的顺序,我们可以依次给 a[0] 和 a[8] 赋值.因为没有对 a ...

  10. SMB重放攻击

    0x01 原理 正常情况下:client端 --------- server端 1.正常情况,当client端登陆时需要先输入username,password和domain[默认是.,表示本地],之 ...