Mysql 全局锁和表锁

MySQL
349
0
0
2022-04-18
标签   MySQL锁

MySQL 的锁可以分为三大类

  • 全局锁
  • 表锁
  • 行锁

全局锁

  • 对整个数据库实例加锁
  • 命令是 Flush tables with read lock (FTWRL) 当你让整个数据库处于只读状态,可以用这个,之后其他线程的所有增删改操作都会被阻塞,包括建表,修改表结构

应用场景

  • 典型场景是做全库逻辑备份,确保不会有其他线程操作数据,但是带来的危险就是业务停摆

mysqldump

  • 官方自带的 mysqldump 使用参数 –single-transaction 时会启动一个事务,这个事务隔离级别为可重复读,确保拿到了一致性视图,就可以安心备份数据了,也不会影响业务
  • 但是数据库引擎必须是 InnoDB

表锁

mysql 表锁有两种

  • 表锁
  • 元数据锁(meta data lock,MDL)

表锁的语法是

lock tables … read/write

主动释放锁的语法

unlock tables;

对表加读锁后,自己也不能对其进行修改;自己和其他线程只能读取该表。 当对某个表执加上写锁后(lock table t2 write),该线程可以对这个表进行读写,其他线程对该表的读和写都受到阻塞;

行锁

mysql 行锁是由引擎层实现的,并不是所有引擎都支持行锁,MyISAM 不支持行锁

两阶段锁

在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。
知道了这个设定,在编写代码中有关于事务的地方,如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。

死锁和死锁检测

当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁。
如我们开启了两个事务,事务A中 update t1 set k=k+1 where id=1,事务B 中 update t1 set k=k+1 where id=1
这时候,事务 A 在等待事务 B 释放 id=2 的行锁,而事务 B 在等待事务 A 释放 id=1 的行锁。 事务 A 和事务 B 在互相等待对方的资源释放,就是进入了死锁状态

两种策略

  • 直接进入等待,直到超时,超时时间参数设置为 innodb_lock_wait_timeout
  • 发起死锁检测,innodb_deadlock_detect 设置为 on 表示开启检测,发现死锁后,主动回滚某个事务,让另一个事务顺利执行。