mysql数据库锁MDL锁的解释

mysql数据库锁MDL锁的解释,第1张

在我们系统中有一张表它的查询概率非常高。 最近有个需求,需要对这个表增加一个字段 ,然而在增加字段的时候发现系统中有多个业务出现了超时 *** 作,那么这个是什么原因导致的呢?经过查阅资料发现是数据库的 MDL锁+事务导致 的。

MDL锁属于表级别的元数据锁。 表级别锁分为数据锁和元数据锁,通常我们说的加锁一般指的是加的数据锁。跟数据锁一样,元数据锁也分读锁和读写锁。

MDL不需要显示使用,在进行表 *** 作时会自动加上 。当对表进行增删改查时,会自动加上MDL读锁;当要对表进行加减字段的结构修改时,会自动加上MDL写锁。

MDL锁的存在,其实是为了保证数据的一致性。 想象一下,假如没有MDL锁,一个查询在遍历表数据的过程中,另外一个线程执行了ALTER TABLE t DELETE COLUMN 'col_1'把col_1这一列删掉了,那查询结果就乱了,结果中是否应该有这一列数据?

:表示正常往下执行

:表示卡住了,即无法往下执行。

解释:

步骤 1 2 正常执行。执行步骤2 时,会申请表customer的MDL的 SHARED_READ 锁。

步骤3 会卡住, 因为此时会申请表customer的MDL的EXCLUSIVE锁,但是事物一的事物没有提交,此时是无法申请到EXCLUSIVE锁,因为它们是互斥的。

步骤4 也会卡住,因为EXCLUSIVE锁和SHARE_READ锁是互斥的, 且EXCLUSIVE锁的优先级更高 ,所以步骤4 也会卡住。

步骤5 事物提交,释放表的SHARE_READ锁,之后就可以执行6 和7 的 *** 作了。

如果先执行事务二,在执行事务三,则是可以成功的,因为alter数据ddl语句,和事物无关。

因此在我们开发的过程中,需要避免大的事务 *** 作,防止占有锁的时间过长。

NO1

互斥量(Mutex)

互斥量是实现最简单的锁类型,因此有一些教科书一般以互斥量为例对锁原语进行描述。互斥量的释放并不仅仅依赖于释放 *** 作,还可以引入一个定时器属性。如果在释放 *** 作执行前发生定时器超时,则互斥量也会释放代码块或共享存储区供其他线程访问。当有异常发生时,可使用try-finally语句来确保互斥量被释放。定时器状态或try-finally语句的使用可以避免产生死锁。

递归锁(Recursive

Lock)

递归锁是指可以被当前持有该锁的线程重复获取,而不会导致该线程产生死锁的锁类型。对递归锁而言,只有在当前持有线程的获取锁 *** 作都有一个释放 *** 作与之对应时,其他线程才可以获取该锁。因此,在使用递归锁时,必须要用足够的释放锁 *** 作来平衡获取锁 *** 作,实现这一目标的最佳方式是在单入口单出口代码块的两头一一对应地使用获取、释放 *** 作,做法和在普通锁中一样。递归锁在递归函数中最有用。但是,总的来说,递归锁比非递归锁速度要慢。需要注意的是:调用线程获得几次递归锁必须释放几次递归锁。

以下为一个递归锁的示例:

[cpp] view plain copy

Recursive_Lock L

void recursiveFunction (int count) {

L->acquire()

if (count >0) {

count = count - 1

recursiveFunction(count)

}

L->release()

}

读写锁(Read-Write

lock) 读写锁又称为共享独占锁(shared-exclusive

lock)、多读单写锁(multiple-read/single-write lock)或者非互斥信号量(non-mutual

exclusion

semaphore)。读写锁允许多个线程同时进行读访问,但是在某一时刻却最多只能由一个线程执行写 *** 作。对于多个线程需要同时读共享数据却并不一定进行写 *** 作的应用来说,读写锁是一种高效的同步机制。对于较长的共享数据,只为其设置一个读写锁会导致较长的访问时间,最好将其划分为多个小段并设置多个读写锁以进行同步。

这个读写锁我们在学习数据库的时候应该很熟悉的哟!

旋转锁(Spin

Lock)

旋转锁是一种非阻塞锁,由某个线程独占。采用旋转锁时,等待线程并不静态地阻塞在同步点,而是必须“旋转”,不断尝试直到最终获得该锁。旋转锁多用于多处理器系统中。这是因为,如果在单核处理器中采用旋转锁,当一个线程正在“旋转”时,将没有执行资源可供另一释放锁的线程使用。旋转锁适合于任何锁持有时间少于将一个线程阻塞和唤醒所需时间的场合。线程控制的变更,包括线程上下文的切换和线程数据结构的更新,可能比旋转锁需要更多的指令周期。旋转锁的持有时间应该限制在线程上下文切换时间的50%到100%之间(Kleiman,1996年)。在线程调用其他子系统时,线程不应持有旋转锁。对旋转锁的不当使用可能会导致线程饿死,因此需谨慎使用这种锁机制。旋转锁导致的饿死问题可使用排队技术来解决,即每个等待线程按照先进先出的顺序或者队列结构在一个独立的局部标识上进行旋转。

学习了这些,果然受益匪浅,在今后的coding中,我得挨个试试咯。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/6666527.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-26
下一篇 2023-03-26

发表评论

登录后才能评论

评论列表(0条)

保存