• MySQL锁机制


    一、锁的分类

    对数据操作的类型:读锁(共享锁)、写锁(排它锁)

    对数据操作对粒度:表锁、行锁

    lock table mylock read,tbl_dept write; #手动增加表锁
    show open tables; #查看表上加过的锁
    unlock tables; #解锁
     
    show status like 'table%';  #分析系统表锁定
    #Table_locks_immediate  产生表级锁定的次数   
    #Table_locks_waited表级锁定争用而发生的等待次数,此值很高,说明存在严重的表级锁争用情况  

    二、表锁(偏读)

    特点:偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低。

    MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁。

    对MyISAM表加读锁,不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求,读锁释放才会执行其他进程的写操作

    对MyISAM表加写锁,会阻塞其他进程对同一表的读和写操作,只有当写锁释放,才会执行其他的进程的读写操作。

    读锁会阻塞写,但不会阻塞读,写锁则会阻塞读和写

    建表语句

    create table mylock(
    id int not null primary key auto_increment,
    name varchar(20)
    )engine myisam;
    
    insert into mylock(name) values('a');
    insert into mylock(name) values('b');
    insert into mylock(name) values('c');
    insert into mylock(name) values('d');
    insert into mylock(name) values('e');
    
    select * from mylock;  

     

    三、行锁(偏写)

    特点:偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

    InnoDB:支持事务,采用了行级锁 

    建表语句

    CREATE TABLE test_innodb_lock(
    a int(11),
    b VARCHAR(16)
    )ENGINE=INNODB;
    
    INSERT INTO test_innodb_lock VALUES(1,'b2');
    INSERT INTO test_innodb_lock VALUES(3,'3');
    INSERT INTO test_innodb_lock VALUES(4,'4000');
    INSERT INTO test_innodb_lock VALUES(5,'5000');
    INSERT INTO test_innodb_lock VALUES(6,'6000');
    INSERT INTO test_innodb_lock VALUES(7,'7000');
    INSERT INTO test_innodb_lock VALUES(8,'8000');
    INSERT INTO test_innodb_lock VALUES(9,'90000');
    INSERT INTO test_innodb_lock VALUES(1,'b1');
    
    CREATE INDEX idx_test_innodb_a ON test_innodb_lock(a);
    CREATE INDEX idx_test_innodb_b ON test_innodb_lock(b);
    
    SELECT * from test_innodb_lock;

    1、行锁定基本演示

    session_01session_02

    关闭事务自动提交 

    set autocommit=0;

    关闭事务自动提交 

    set autocommit=0;

    UPDATE test_innodb_lock SET b='4001' WHERE a=4;  
    select * from test_innodb_lock

    事务未提交,看到4000

    select * from test_innodb_lock

    事务提交 commit;

    事务提交 commit;
    select * from test_innodb_lock select * from test_innodb_lock
    UPDATE test_innodb_lock SET b='4002' WHERE a=4;

     操作同一行,存在行锁,被阻塞

    UPDATE test_innodb_lock SET b='4003' WHERE a=4;

    UPDATE test_innodb_lock SET b='4005' WHERE a=4;

     操作不同行,不存在行锁,正常执行

    UPDATE test_innodb_lock SET b='90001' WHERE a=9;

    2、无索引行锁升级为表锁

    session_01 session_02
    UPDATE test_innodb_lock SET a=41 WHERE b=4000;

    更新不同的行操作被阻塞

    UPDATE test_innodb_lock SET b='90001' WHERE a=9;

    3、什么是间隙锁:

    当用范围条件而不是相等条件检索数据,并请求共享或排他锁,InnoDB会给符合条件的已有数据记录的索引项加锁。

    对于键值在条件范围内但并不存在的记录,叫做“间隙”。

    session_01 session_02
    UPDATE test_innodb_lock SET b= ‘0629’ WHERE a>1 and a<6;

    新增操作被阻塞

    INSERT INTO test_innodb_lock values (2,'2000');

    4、如何锁定一行?

    session_01 session_02

    BEGIN;

    SELECT * from test_innodb_lock where a=8 for UPDATE;

    更新操作被阻塞

    UPDATE test_innodb_lock set b='1000' where a=8;

    COMMIT;  

    5、行锁分析

    show status like 'innodb_row_lock%';
    #Innodb_row_lock_current_waits:当前正在等待锁定的数量
    #Innodb_row_lock_waits:等待总次数
    #Innodb_row_lock_time:等待总时长
    #Innodb_row_lock_time_avg:等待平均时长

    四、页锁(了解)

    开销和加锁时间介于表锁和行锁之间,

    会出现死锁

    锁定粒度介于表锁和行锁之间,并发度一般 

  • 相关阅读:
    一点一点学习GIt
    17-ajax向后端提交POST请求
    16-djongo中间件学习
    ES6快速入门
    15 Django组件——中间件
    导入Scrapy 项目报错:no module named scrapy
    slf4j + logback 输出日志:mybatis sql语句
    java实现链表
    Log4j2.xml的日志设置
    java多线程之生产者消费者经典问题
  • 原文地址:https://www.cnblogs.com/wjh123/p/11219477.html
Copyright © 2020-2023  润新知