锁机制是影响查询性能的另一个重要因素。当有多个用户并发访问数据库中某一资源的时候,为了保证并发访问的一致性,数据库必须通过锁机制来协调这些访问。
我们可以认为查询的时间开销主要包括两部分,即查询本身的计算时间和查询开始前的等待时间,所以说索引影响的是前者,而锁机制影响的是后者。
减少表锁定等待
MySQL 为 MyISAM 类型表提供了表级别的锁定。MyISAM 的表锁定可以允许多个线程同时读取数据,比如 select 查询,它们之间是不需要锁等待的。但是对于更新操作(如 update 操作),它会排斥对当前表的所有其它查询,包括 select 查询。除此之外,更新操作有着默认的高优先级,这意味着当表锁释放后,更新操作将先获得锁定,然后才轮到读取操作。也就是说,如果有很多 update 操作排着长队,那么对当前表的 select 查询必须等到所有的更新都完成之后才能开始。
在一些特定的情况下,慢速查询对于整体性能的影响是非常严重的,举个例子。
CREATE TABLE `count_t` ( `id` INT NOT NULL AUTO_INCREMENT , `count` INT NOT NULL DEFAULT '0' , PRIMARY KEY (`id`) ) ENGINE = MyISAM;
我们为这个表填充了10万行记录,其中 count 字段为 0 到 999 的随机整数。现在我们需要一个比较慢速的 update 操作,如下所示:
接下来,我们编写 PHP 程序用来执行这个 update 操作,然后用 ab 模拟 10 个并发用户来请求这个 PHP 程序,这使得刚才的 update 操作语句会被执行 10 次,目的是让这个数据表忙于长时间的 update 操作。
在启动 ab 后不久,我们马上在 MySQL 命令行中发起一个 select 查询,如下所示:
mysql> select * from count_t where id=1;
这个查询并没有返回结果,而像是陷入了沉思。这时我们在另一个 MySQL 命令行会话中监视所有的线程状态,因为我们想知道到底发生了什么。 show processlist 的结果如下所示:
我们看到除了 show processlist 本身的线程之外,还有几个 update 线程和 1 个 select 线程,其中只有一个 update 线程的状态为 Updating ,而其它的几个 update 线程 和 1个 select 线程都处于 Locked 状态,这意味着它们正在等待表锁的释放、
终于,select 查询结束了,结果如下所示:
行锁定带来了什么
如果你的站点主要依靠用户创造内容,那么频繁的数据更新在所难免,它将会给 select 等读取操作带来很大的影响,这时候可以使用行锁来解决问题,MySQL 在 Innodb 类型表中提供了行锁的支持,将刚才的 count_t 表转为 Innodb 类型。
我们同样用 ab 模拟 10 个并发用户来执行 update 操作,同时我们监视 MySQL 线程,如下所示:
可以看到有多个 update 线程在执行,它们的状态都为 updating 。这时候我们在 MySQL 命令行中执行一个 select 查询,如下所示:
查询瞬间返回结果,用时 0.00 秒。即便还有多个 update 操作在执行,select 查询还是迅速地获得结果。update 和 select 来自不同的线程,并且针对不同的记录行,所以它们可以轻松地并发进行,这就是行锁真正带给我们的惊喜。
行锁定真的好吗?
我们再来模拟一个更加接近实际情况的场景,为此,我们用 PHP 编写了以下程序:
<?php $servername = "localhost"; $username = "root"; $password = ""; $dbname = "runoob"; // 创建链接 $conn = new mysqli($servername, $username, $password, $dbname); // 检查链接 if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); } $sql = "UPDATE `count_t` SET `count`=`count`+1"; $conn->query($sql); $conn->close();
这段程序做了两件事情,首先它执行一次慢速的 update 操作,然后执行 10000 次快速的 select 查询。我们用 ab 模拟 20 个并发,每个用户请求一次程序,通过使用 MyISAM 和 Innodb 两种不同类型的锁定机制,我们来分别记录总执行时间。
首先是 MyISAM 类型表,测试结果的关键部分如下所示:
接下来是 Innodb 类型表,结果如下所示:
使用 Innodb 的行锁定在这里并没有比 MyISAM 的表锁定表现得更好,反而还略有不如。在压力测试的时候,我们通过 show PROCESSLIST 来监视线程状态,当使用 MyISAM 类型表的时候,我们看到除了一个正在 Updating 的 update 线程之外,其它的 update 线程都在 Locked,而使用 Innodb 行锁定的时候,我们看到所有的 update 线程的状态都是 Updating,可为什么它的总时间还不如前者呢 ?
这里我们需要清楚的是,锁定只是一种逻辑层面的约束,即便是同时拥有 Updating 的状态,也不能加速这些 update 操作的总时间,因为磁盘的物理写操作最终还是依次进行的。
相关推荐
有两种:1,当用户没有操作程序时锁定程序 2,当用户没有操作系统时锁定程序
11.3 锁定与等待 11.4 事务性表的性能 11.5 使用查询缓存 11.6 临时表 11.7 线程池 11.8 反范式化设计 11.9 放弃关系型数据库 第12章 Web负载均衡 12.1 一些思考 12.2 HTTP重定向 12.3 DNS负载均衡 12.4 ...
11.3 锁定与等待 11.4 事务性表的性能 11.5 使用查询缓存 11.6 临时表 11.7 线程池 11.8 反范式化设计 11.9 放弃关系型数据库 第12章 Web负载均衡 12.1 一些思考 12.2 HTTP重定向 12.3 DNS负载均衡 12.4...
11.3 锁定与等待 11.4 事务性表的性能 11.5 使用查询缓存 11.6 临时表 11.7 线程池 11.8 反范式化设计 11.9 放弃关系型数据库 第12章 Web负载均衡 12.1 一些思考 12.2 HTTP重定向 12.3 DNS负载均衡 12.4...
IE主页设置工具V1.0 软件功能:锁定主页、解除锁定、清理...使用“清理缓存”功能,需耐心等待一段时间,完成后有提示窗出现。 4.程序开发wszjf,可随意传播,翻版不究。" 5.问题和建议请mail:wssgzjf@163.com。
本源码主要演示Delphi 锁定鼠标和键盘 10秒后解锁,数字键、字母键和大部分功能键以及鼠标全部键都将锁定不能操作,但对键盘中的“Power”键、“Sleep... // 等待10秒 forbid(False); // 允许键盘鼠标 end; end;
严格的两阶段锁定协议用于并发控制,使用等待死锁方法来处理死锁 程序的设计与实现: 我设计了两个HashMap来跟踪所有事务,并设计了PriorityQueue来存储等待的事务。 我们将所有操作的列表存储在交易表(TT)和锁定...
jquery+strtus 带有等待动画显示,里面的注释很详细,等待时可以指定锁定区域和锁定起始位置,也可以全屏锁定。 还有一点注意:由于上传代码匆忙,忘记一处,// 解锁 bgObj.onclick = function() { new screen...
该策略决定了当一个帐户被锁定后,需要等待多长时间(以分钟为单位),系统才自动将记录的失败次数清零。可设置的值是0~99999。只有当指定了帐户锁定阈值时,该策略设置才有意义。;在桌面上按下Win键+R键,打开...
等待历时一周的锁定时间仿真,处理大型环路滤波器的大尺寸版图封装,还要在设计中解决 PLL 稳定性问题,这一切都让设计人员举步维艰。Instantaneous Technologies 发明的瞬时锁定环 (ILL) 技术可让上述所有问题...
@概括一种易于使用的锁定机制,具有锁定超时功能和有限的等待耐心。@用法 L = DLock( "LOCKNAME" ) # step A: instantiate, with nameacquired = L.LoopWhileLocked_ThenLocking() # step B: waitThenTryLockingif ...
当用户多次登录失败的时候,我们应该将账户锁定,等待一定的时间之后才能再次进行登录操作。今天小编给大家分享Spring Security实现多次登录失败后账户锁定功能,感兴趣的朋友一起看看吧
自动抢svn文件锁定,对于svn文件,多人使用时,为了降低等待时间,浪费时间资源,自动锁定svn文件。
一种无需锁定和等待的环形FIFO算法,效率比较高
该组件主要用于,采用AJAX异步加载数据时,锁定用户操作界面。
锁定状态时系统用3位数码管显示OFF,用3位数码管显示成功开锁次数;成功开锁时用3位数码管显示888,用3位数码管显示成功开锁次数。 2、密码设定功能: 通过一个4×4的矩阵式键盘可以任意设置用户密码(1-16位长度...
回发时锁定页面
在应用中,我们经常会碰到sql执行很慢,但是数据库cpu和内存使用率又不高的情况,类似的问题基本上由于锁,排序等原因造成,本文主要描述如何去定位锁等待问题,谁在锁等待?等待谁持有的锁?锁在那个表?
线程编程方面:反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一...若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。