共享读锁(S)
手动加锁 select .... lock in share mode 允许一个事务去读一行 阻止其他事务获取相同数据集的排他锁
排他写锁(X)
自动加锁 允许获得排他写锁的事务更新数据 阻止其他事务取得相同数据集的共享读锁(不是普通读) 和排他写锁
- DML(insert、update、delete)
- select ... from udpate
整体分类
表级锁使用
表读锁
事务1给mylock表添加读锁 事务1查询mylock表可以读取到数据 事务1不可以查询其他表数据 事务2普通查询mylock表 没有加锁 可以查到 通过MVCC机制查询数据的历史版本 事务2更新mylock表id为2的数据 需要先获取这条数据的行锁 才可以进行修改 但此时是获取不到的 因为事务1还未释放mylock表的读锁 所以事务2只能等待事务1释放mylock表的读锁 才能够获取到行锁 事务1释放了mylock表的读锁 那么则可以查询其他表的数据了 事务2也获取到id为2的这条数据的行锁 执行更新操作
表写锁
事务1给mylock添加表写锁 事务1可以查询mylock数据 事务1不可以查询其他表数据 事务1更新mylock表id为2的数据 可以执行 事务2查询mylock数据 查询阻塞 因为事务1还未释放mylock表的写锁 事务1释放mylock表的写锁 事务2的查询得以继续执行 事务1页可以访问其他表数据了
元数据锁的使用
元数据读锁
事务1开启事务 事务1查询mylock表 此时会加一个MDL读锁 事务2修改mylock表结构 此时会被阻塞 事务1提交事务或回滚事务 事务2才得以修改完成
行级锁分类及使用
查询行级锁状态
show status like 'innodb_row_locks'
行级锁的使用
事务1 开始事务 事务1 查询mylock表id为1的数据 id列为索引列 加行读锁 事务2更新id为2的数据 因未锁定该行 所以可以更新 事务2更新id为1的数据 该行的行读锁还未释放 此时修改被阻塞 事务1提交事务 事务2对id为1这条数据的更新才得以执行 "注" 使用索引加行锁 未锁定的行可以访问
行读锁升级为表锁
未使用索引的行级锁会升级为表锁
事务1开始事务 事务1查询mylock表 查询条件是name='c' 并手动给name='c'添加行读锁 但name列并未使用索引 所以行读锁就会升级为表级锁 事务2更新mylock表id为2的数据 就会被阻塞 事务1提交或回滚事务 表级锁就会被释放 事务2的更新操作就可以获取到行级锁 然后执行更新操作
行写锁
主键索引产生记录锁
事务1开始事务 事务1查询mylock表id为1的数据 并添加行写锁 事务2查询mylock表id为2的数据 可以访问 事务2查询mylock表id为1的数据 可以访问 不加锁 事务2 查询mylock表id为1的数据 添加读锁 此时被阻塞 事务1提交 释放了id为1的行写锁 事务2 加读锁获取id为1的数据得以执行