BlogBlog
首页
  • Vue
  • TypeScript
  • React
  • Angular
  • Node.js
  • 小程序
  • Flutter
  • 数据产品
  • 大数据

    • Hadoop
    • Hive
    • Spark
  • MySQL
  • Redis
  • Java
  • Python
  • Golang
GitHub
首页
  • Vue
  • TypeScript
  • React
  • Angular
  • Node.js
  • 小程序
  • Flutter
  • 数据产品
  • 大数据

    • Hadoop
    • Hive
    • Spark
  • MySQL
  • Redis
  • Java
  • Python
  • Golang
GitHub

06-07-锁

锁的种类

mysql锁大致可以分成全局锁、表级锁和行锁三类

  • 全局锁, 又称为数据库锁,是对整个数据库实例加锁,对整个数据库实例的DDL和DML操作都会被阻塞,直到锁释放。
  • 表级锁
    • 表锁, Table Lock,是对表加锁,对表的DDL和DML操作都会被阻塞,直到锁释放。
    • 元数据锁, meta data lock, MDL
  • 行锁
    • 共享锁, Shared Lock,又称为读锁,是对一行或多行加锁,其他事务只能对该行或多行进行读操作,直到锁释放。
    • 排他锁, Exclusive Lock,又称为写锁,是对一行或多行加锁,其他事务不能对该行或多行进行任何操作,直到锁释放。
    • record lock,又称为next-key lock,是对索引记录加锁,在RR隔离级别下,对索引记录加的锁,其他事务只能在当前索引记录和相邻的记录之间进行加锁,直到锁释放。
    • gap lock,又称为间隙锁,是对索引记录之间的间隙加锁,在RR隔离级别下,对索引记录之间的间隙加的锁,其他事务只能在当前索引记录和相邻的记录之间进行加锁,直到锁释放。
    • next-key lock,又称为gap lock,是对索引记录之间的间隙加锁,在RR隔离级别下,对索引记录之间的间隙加的锁,其他事务只能在当前索引记录和相邻的记录之间进行加锁,直到锁释放。

全局锁

Flush tables with read lock;

官方自带的逻辑备份工具是 mysqldump,当 mysqldump 使用参数–single-transaction 的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。

但当引擎不支持事务时,只能使用FTWRL 命令了。不推荐不使用 set global readonly=true,readonly会被其他逻辑使用(比如判断主从),readonly发生异常会保持该状态。

表级锁

表锁的语法是 lock tables … read/write。
MDL不需要显式使用,在访问一个表的时候会被自动加上。
当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

当一个长事务还没提交,进行表结构变更操作,会导致后面的事务block。当客户端有重试机制时,新起session请求,会导致库的线程很快就会爆满。

如何安全地给小表加字段?
避免长事务。

在 alter table 语句里面设定等待时间。
MariaDB 已经合并了 AliSQL 的这个功能,所以这两个开源分支目前都支持 DDL NOWAIT/WAIT n 这个语法。

07 | 行锁功过:怎么减少行锁对性能的影响

行锁
Mysql行锁由引擎层实现

两阶段锁
行锁需要事务结束时才释放,这就是两阶段锁。
所以需要合理安排事务中sql执行顺序,尽量把容易冲突的更新语句放在后面。

死锁和死锁检测
设置超时时间,innodb_lock_wait_timeout。
死锁检测,发现死锁主动回滚某个事务,innodb_deadlock_detect 默认on。
假设1000个同时更新一行,则死锁检测操作就是 100 万这个量级的。即使没有死锁,检测也会消耗大量的 CPU 资源。
解决方案:

业务不会出现死锁,可以临时关闭。
在客户端控制并发。
修改MySQL 源码,并发进入引擎之前排队。
将一行数据改为多行,如将一个余额账户分为多个,但在数据减少操作时需考虑小于0的情况。
最近更新:: 2025/5/4 09:43
Contributors: alice