• MySQL会发生死锁吗?


    SHOW ENGINE INNODB STATUS;来查看死锁日志:

    SHOW PROCESSLIST;查看进程

    MySQL的InnoDB引擎事务有4种隔离级别,主要是为了保证数据的一致性。

    InnoDB引擎提供了行级锁,表锁。MyISAM提供了表锁,如题,MySQL会发生死锁吗?

    会,在InnoDB引擎下,RR(REPEATABLE-READ)级别,如果多个事务争抢同一个资源,会发生死锁。在RR级别下,MySQL提供了next-key lock。假如一个索引的行有10,11,13,20
    那么可能的next-key lock的包括:
    (无穷小, 10]
    (10,11]
    (11,13]
    (13,20]
    (20, 无穷大)

    即:当你查询12时,如果数据未查到,那么将对(12,13]范围内的数据进行锁定。next-key lock的定义可以到官方具体查看,这里做个演示。

    CREATE TABLE `user` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(200) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1111 DEFAULT CHARSET=utf8;
    
     
    image-20190304142624761
    //查看隔离级别,
    show variables like '%tx_isolation%';
    // 设置隔离界别
    SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
    // 不设置自动提交
    SET autocommit = 0;
    

    死锁演示

    1. 首先将隔离级别都设置为RR级别的,并且不让事务自动提交
    2. 根据上面的数据,在事务1中查询
    // 得到空结果集,此时锁定的范围是(33,100]
    select * FROM user where id=33 for update;
    
    1. 在事务2中也进行查询
    // 查询到空的结果,在事务2中锁定的范围是(34,100]
    select * FROM user where id=34 for update
    
    1. 在事务1中插入数据
    // 虽然事务1锁定了范围,事务2也锁定了范围
    insert into user values(35,'ac',10);
    
     
    image-20190304143355381
    1. 在事务2中也插入数据
    insert into user values(34,'ac',10)
    
     
    image-20190304143707234
    1. 可以发现已经发生了死锁

    解决办法

    1. 设置死锁的超时时长

    innodb_lock_wait_timeout=500

    1. 查询到当前正在锁定的事务线程,将其杀死
    // 可以看到正在运行的事务线程,还有运行状态
    SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
    
    //trx_mysql_thread_id为上一条命令获取的结果,将具体的数字替换一下即可。
    kill trx_mysql_thread_id
    

     

  • 相关阅读:
    java陷阱一箩筐面试
    应用MVC设计模式解决J2ME应用程序导航问题 mingjava
    我怎么了
    运营商掘宝手机游戏 无限“钱途”引人竞折腰
    网络工程师考试大纲
    java 正则
    java集合使用——LinkedList
    java集合使用——HashMap
    java集合使用——HashSet
    JAVA集合使用——基本概念
  • 原文地址:https://www.cnblogs.com/cheyunhua/p/10483050.html
Copyright © 2020-2023  润新知