mysql怎么防止锁 mysql上锁( 二 )


全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将阻塞 。其典型的使用场景就是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性 。但是对数据库加全局锁是有弊端的 , 如在主库上备份,那么在备份期间都不能执行更新,业务会受影响,第二如果是在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志,会导致主从延迟 。
解决办法是在innodb引擎中 , 备份时加上--single-transaction参数来完成不加锁的一致性数据备份 。
添加全局锁: flush tables with read lock; 解锁 unlock tables 。
表级锁,每次操作会锁住整张表.锁定粒度大,发送锁冲突的概率最高,并发读最低,应用在myisam、innodb、BOB等存储引擎中 。表级锁分为: 表锁、元数据锁(meta data lock, MDL)和意向锁 。
表锁又分为: 表共享读锁 read lock、表独占写锁write lock
语法: 1、加锁 lock tables 表名 ... read/write
2、释放锁 unlock tables 或者关闭客户端连接
注意: 读锁不会阻塞其它客户端的读,但是会阻塞其它客户端的写,写锁既会阻塞其它客户端的读,又会阻塞其它客户端的写 。大家可以拿一张表来测试看看 。
元数据锁,在加锁过程中是系统自动控制的,无需显示使用,在访问一张表的时候会自动加上,MDL锁主要作用是维护表元数据的数据一致性 , 在表上有活动事务的时候,不可以对元数据进行写入操作 。为了避免DML和DDL冲突,保证读写的正确性 。
在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更操作时,加MDL写锁(排他).
查看元数据锁:
select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema_metadata_locks;
意向锁 , 为了避免DML在执行时 , 加的行锁与表锁的冲突,在innodb中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查 。意向锁分为,意向共享锁is由语句select ... lock in share mode添加 。意向排他锁ix,由insert,update,delete,select 。。。for update 添加 。
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_lock;
行级锁,每次操作锁住对应的行数据,锁定粒度最小,发生锁冲突的概率最高,并发读最高 , 应用在innodb存储引擎中 。
innodb的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁 , 对于行级锁,主要分为以下三类:
1、行锁或者叫record lock记录锁,锁定单个行记录的锁,防止其他事物对次行进行update和delete操作,在RC,RR隔离级别下都支持 。
2、间隙锁Gap lock,锁定索引记录间隙(不含该记录) , 确保索引记录间隙不变,防止其他事物在这个间隙进行insert操作,产生幻读 , 在RR隔离级别下都支持 。
3、临键锁Next-key-lock,行锁和间隙锁组合 , 同时锁住数据,并锁住数据前面的间隙Gap,在RR隔离级别下支持 。
innodb实现了以下两种类型的行锁
1、共享锁 S: 允许一个事务去读一行 , 阻止其他事务获得相同数据集的排他锁 。
2、排他锁 X: 允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁 。
insert 语句 排他锁 自动添加的
update语句 排他锁 自动添加
delete 语句 排他锁 自动添加
select 正常查询语句 不加锁。。。

推荐阅读