全局锁
全局锁:对整个数据库实例进行加锁。
使用全局锁的命令:Flush tables with read Lock(FTWRL)。加了该命令以后,整个数据处于只读状态,其他所有进来的除了查询之外的操作都会被阻塞
使用场景:全库逻辑备份
在全库逻辑备份的过程中,官方自带的逻辑备份工具是mysqldump,mysqldump使用参数single-transaction的时候,导数据之前就会启动一个事务来确保拿到一致性视图。由于MVCC的支持,这个过程可以正常更新。但是mysqldump方法的缺点是,要求所使用的引擎必须能够支持可重复读这个隔离级别。
在全库逻辑备份过程中,之所以不采用set global readonly=true的方式是因为:1 在有些系统中readonly的值会被拿来做其他逻辑。2 在异常处理机制上有差异。当客户端发生异常断开,使用了FTWRL命令的MySQL会自动释放这个全局锁,整个数据库回到正常的状态。而readonly命令的系统,则会一直保持readonly状态,导致数据库长时间处于不可写状态。
表级锁---------表锁
表锁的语法:Lock table…read/write。使用表锁之后除了会限制别的线程的读写操作,也会限制自己线程接下来的操作对象
表级锁----------元数据锁(MDL)
MDL不需要显示使用,在访问一个表时,会被自动加上。
MDL读锁:当对表进行增删改查操作时,在该表上添加MDL读锁。MDL读锁之间不互斥;
MDL写锁:当对表进行结构变更操作时,在该表上添加MDL写锁。MDL读写、写写之间互斥;
事务中的MDL锁,在语句执行时开始申请,但是在语句结束以后并不会马上释放,而会等到整个事务提交后在释放。
DDL:对表的字段进行操作
DML:对表的数据进行操作
如何安全的给小表加字段?
1 解决长事务,事务不提交,就会一直占用着MDL锁。当要做DDL时,刚好有长事务在执行,可以考虑先暂定这个DDL或者kill这个事务
2 或者在alter table语句里面设置等待时间,如果这个指定的等嗲时间内,能够拿到MDL写锁最好,拿不到的化先不阻塞后面额业务语句,先放弃。之后开放人员或者DBA在通过重试命令重复这个过程。
(所谓事务:是指访问并可能操作各种数据项的一个数据库操作序列。事务内的操作要么全部执行,要么全部不执行,是一个不可分割的工作单位)
行锁
1 行锁的概念
对数据表中的行进行加锁。行锁是在引擎层,由各个引擎自行 实现的。(不是所有引擎都支持行锁,比如myISAM)
2 两阶段锁协议
在InnoDB中,行锁是在需要的时候加上的,但不是不需要了就立刻释放,而是需要等待对应的事务结束时才释放。
从两阶段锁协议的概念出发,当一个事务中,需要对多行进行添加行锁操作时,把最后可能造成所冲突、最可能影响并发度的锁尽量往后放。
3 死锁
在并发系统中,不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这个几个线程进入无线等待的状态
4 解决死锁的方法
策略一:处于死锁的线程直接进入等待,直到超时。设置参数:innodb_lock_wait_timeout
策略二:发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,这样其他事务就可以继续执行。设置参数:innodb_deaclock_detect设置为on
5 出现所有事物都要更新同一行的场景?
每个新来的被堵住的线程,都会需要判断是不是进入了死锁状态,当堵住的线程越来越长,并且检测到其实不是死锁,这就会造成资源巨大的浪费。因此,需要思考,如何解决有这种热点行更新导致的性能问题
策略一:当能确保这个业务一定不会出先死锁,可以吧死锁检测关掉
策略二:控制并发度。在服务器端,对于向同行的更新在进入引擎之前排队。这样InnoDB内部就不会有大量的死锁检测工作
策略三:将一行改成逻辑上的多行来减少锁冲突。
数据库学习之全局锁、表锁、行锁
最新推荐文章于 2024-07-26 16:04:09 发布