• 004 --Mysql中的锁的问题


    死锁

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

    MySQL 中的事务

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

    关于自动提交(AUTOCOMMIT)

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

    SHOW VARIABLES LIKE 'autocommit';

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

    mysql> SHOW VARIABLES LIKE 'autocommit';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | ON    |
    +---------------+-------+
    1 row in set (0.00 sec)

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

    set autocommit=0;

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

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

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

    CREATE TABLE `user` (
      `id`   BIGINT(20) NOT NULL AUTO_INCREMENT,
      `name` VARCHAR(20)         DEFAULT '',
      `age`  INT(11)             DEFAULT '0',
      PRIMARY KEY (`id`)
    )
      ENGINE = InnoDB
      DEFAULT CHARSET = utf8mb4

    接着关闭自动提交功能:

    mysql> set autocommit=0;

    然后插入一个数据:

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

    接着查看数据:

    mysql> select * from user;
    +----+------+------+
    | id | name | age  |
    +----+------+------+
    |  1 | xys  |   18 |
    +----+------+------+
    1 row in set (0.00 sec)

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

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

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

    mysql> exit
    Bye
    >>> mysql -u root -p
    Enter password:
    
    mysql> use test;
    Database changed
    mysql> select * from user;
    Empty set (0.00 sec)
    
    mysql>

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

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

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

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

    mysql> set autocommit=1;
    mysql> SHOW VARIABLES LIKE 'autocommit';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | ON    |
    +---------------+-------+
    1 row in set (0.00 sec)

    然后插入一个数据:

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

    接着查看数据:

    mysql> select * from user;
    +----+------+------+
    | id | name | age  |
    +----+------+------+
    |  1 | xys  |   18 |
    +----+------+------+
    1 row in set (0.00 sec)

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

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

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

    BEGIN;
    INSERT INTO user (`id`, `name`, `age`) VALUES (1, 'xys', 18);
    COMMIT;
  • 相关阅读:
    【IT笔试面试题整理】把n个骰子扔在地上,所有骰子朝上一面的点数之和为S概率转
    面试题位操作
    微软面试题 寻找数组中出现的唯一重复的一个数
    【IT笔试面试题整理】给定二叉树先序中序,建立二叉树的递归算法
    【IT笔试面试题整理】 二叉树任意两个节点间最大距离
    面试题堆栈和队列
    LRU cache实现 Java 转
    【IT笔试面试题整理】有序数组生成最小高度二叉树
    Unity3d Asset Store下载的资源在哪?
    Xcode 6 如何将 模拟器(simulator) for iphone/ipad 转变成 simulator for iphone
  • 原文地址:https://www.cnblogs.com/yxllovetm/p/10091426.html
Copyright © 2020-2023  润新知