zoukankan      html  css  js  c++  java
  • MySQL表锁和行锁

      本次主要是测试一下MySQL的select ... for update这种悲观锁的表锁和行锁,版本:MySQL5.7.20,存储引擎 InnoDB 操作系统:Windows10 64位,工具:navicat for mysql 11

    表名称:test_order,主键是id;

      要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交,所以我们需要手动设置autocommit=0;

    1. 对主键进行加锁:

    navicat起一个命令行,设置autocommit=0,并且对id=1的记录进行加锁;

    mysql> select * from test_order;
    +----+--------+--------+----------+
    | id | status | name   | goods_id |
    +----+--------+--------+----------+
    |  1 |      1 | 茅台   | 123      |
    |  2 |      2 | 五粮液 | 345      |
    |  3 |      3 | 剑南春 | 567      |
    +----+--------+--------+----------+
    3 rows in set
    
    mysql> set autocommit = 0;
    Query OK, 0 rows affected
    
    mysql> select * from test_order where id = 1 for update;
    +----+--------+------+----------+
    | id | status | name | goods_id |
    +----+--------+------+----------+
    |  1 |      1 | 茅台 | 123      |
    +----+--------+------+----------+
    1 row in set

    navicat再起一个命令行

    mysql> select * from test_order where id = 1;
    +----+--------+------+----------+
    | id | status | name | goods_id |
    +----+--------+------+----------+
    |  1 |      1 | 茅台 | 123      |
    +----+--------+------+----------+
    1 row in set
    
    mysql> select * from test_order where id = 1 for update;
    1205 - Lock wait timeout exceeded; try restarting transaction
    mysql> select * from test_order where id = 2 for update;
    +----+--------+--------+----------+
    | id | status | name   | goods_id |
    +----+--------+--------+----------+
    |  2 |      2 | 五粮液 | 345      |
    +----+--------+--------+----------+
    1 row in set
    
    mysql> 

    结论:对主键进行锁定时,对常规的select操作无影响,再次锁id=1的记录时,发现已经被锁,而查询其他的数据则没问题;

    2. 对非主键非索引加锁

    mysql> select * from test_order where status = 1 for update;
    +----+--------+------+----------+
    | id | status | name | goods_id |
    +----+--------+------+----------+
    |  1 |      1 | 茅台 | 123      |
    +----+--------+------+----------+
    1 row in set

    另起一个命令行

    mysql> select * from test_order where id = 1 for update;
    1205 - Lock wait timeout exceeded; try restarting transaction
    mysql> select * from test_order where id = 2 for update;
    1205 - Lock wait timeout exceeded; try restarting transaction

    结论:对非主键非索引加锁时,锁的是整张表;

    3. 对非主键索引加锁

    我们对status这个字段加上索引,然后再测试:

    mysql> set autocommit = 0;
    Query OK, 0 rows affected
    
    mysql> select * from test_order where status = 1 for update;
    +----+--------+------+----------+
    | id | status | name | goods_id |
    +----+--------+------+----------+
    |  1 |      1 | 茅台 | 123      |
    +----+--------+------+----------+
    1 row in set

    再起一个命令行

    mysql> select * from test_order where id = 1 for update;
    1205 - Lock wait timeout exceeded; try restarting transaction
    mysql> select * from test_order where id = 2 for update;
    +----+--------+--------+----------+
    | id | status | name   | goods_id |
    +----+--------+--------+----------+
    |  2 |      2 | 五粮液 | 345      |
    +----+--------+--------+----------+
    1 row in set

    结论:对于索引字段来说,使用的是行锁;

    总结:MySQL的select ... for update这种悲观锁,有两种锁定级别:行锁(Row Lock ),表锁(Table Lock)。在对表进行进行加锁的时候,由于主键本身就是索引,所以,对包含索引的字段加的是行锁,而对于非索引字段,加的是表锁;Mysql InnoDB存储引擎默认的是Row Lock,所以查询的时候尽量使用索引。

  • 相关阅读:
    Java基础知识强化102:线程间共享数据
    Java(Android)编程思想笔记02:组合与继承、final、策略设计模式与适配器模式、内部类、序列化控制(注意事项)
    Android开发经验01:31个Android开发实战经验
    TCP/IP协议原理与应用笔记19:IP分组的交付和路由选择
    Android 高级UI设计笔记08:Android开发者常用的7款Android UI组件(转载)
    Java(Android)编程思想笔记01:多态性的理解
    Java基础知识强化之集合框架笔记75:哈希表
    重置 linux系统后要配置的基本组件操作
    记一个空格导致的三小时排查
    windows无法启动redis服务,错误码1067
  • 原文地址:https://www.cnblogs.com/xiaozhang2014/p/7787545.html
Copyright © 2011-2022 走看看