[MySQL] MySQL锁
锁的类型 Mysql的锁,根据加锁的范围可以分为全局锁、表级锁和行锁三类 全局锁 要使用全局锁,执行下面这条命令: flush tables with read lock 执行之后,整个数据库就处于只读状态,这时其他线程执行以下操作,就会被阻塞 对数据的增删改,比如insert、delete、update等 对表结构的更改操作,比如alter table、drop table等 要释放全局锁,执行下面的命令: unlock tables 全局锁的应用场景: 全局锁主要用于做全库逻辑备份,这样在备份数据库期间,不会因为数据或者结构的更新,而出现备份文件的数据与预期的不一样 加全局锁带来的缺点:会导致业务停滞,因为加全局锁之后,整个数据库都只是只读状态,不能更新数据 可以通过开启事务,在可重复读的隔离级别下,即使其他事务更新了表的数据,也不会影响备份数据库时的Read View, 备份数据库的工具是mysqldump ,在使用mysqldump时加上-single-transaction 参数的时候,就会在备份数据库之前开启事务 表级锁 MySQL里面表级锁有以下几种: 表锁 元数据锁(MDL) 意向锁 AUTO-INC锁 表锁 使用下面的命令对表加锁和释放锁 // 加读锁 lock tables <table_name> read; // 写锁 lock tables <table_name> write; // 释放锁 unlock tables; 表锁会影响别的线程和本线程的读写操作 元数据锁(MDL) 对于MDL,我们不需要显示使用,因为当我们在对数据库进行操作时,会自动给这个表上加MDL: 对一张表进行CURD操作时,加的是MDL读锁 对一张表做结构变更操作的时候,加的是MDL写锁 MDL是为了保证当前用户对表执行CRUD操作时,防止其他线程对这个表结构做了变更 MDL是在事务提交之后才会释放,这意味着事务执行期间,MDL是一直持有 需要注意的是,在事务启用之后,如果事务A没有提交,此时如果有表结构的修改请求发起,就会发生阻塞,这个阻塞也会导致其他CURD的请求被阻塞住 这是因为申请MDL锁的操作会形成一个队列,队列中写锁获取优先级大于读锁,一旦出现MDL写锁等待,会阻塞该表后续的CRUD操作 意向锁 在使用InnoDB引擎的表里对某些记录加上共享锁之前,需要先在表级别加上一个意向共享锁 在使用InnoDB引擎的表里对某些记录加上独占锁之前,需要先在表级别加上一个意向独占锁 在执行insert、update、delete操作时,需要先对表上加 意向独占锁,然后对该记录加独占锁 而普通的select是不会加行级锁,普通的select语句是利用MVCC实现一致性读,是无锁的 // select也是可以对记录加共享锁和独占锁, // 先在表上加上意向共享锁,然后对读取的记录加共享锁 select ... lock in share mode; // 先表上加上意向锁,然后再读取记录加独占锁 select ... for update 意向锁的目的是为了快速判断表里是否有记录被加锁 AUTO-INC锁 表里面的主键通常设置成自增的,在插入数据时,可以不指定主键的值,数据库会自动给主键赋值递增的值,这主要是通过AUTO-INC锁实现的 Auto-Inc锁是特殊的表锁机制,不是在一个事务提交后才释放,而是再执行完插入语句后就会立即释放 行级锁 InnoDB引擎是支持行级锁的,而MyISAM引擎并不支持行级锁 行级锁的类型主要有三类: ...