mysql死锁是什么

mysql中,死锁指的是在两个或两个以上不同的进程或线程中,因争夺资源而造成的一种互相等待的现象;由于存在共同资源的竞争或进程(或线程)间的通讯而导致各个线程间相互挂起等待,如果没有外力作用,最终会引发整个系统崩溃。mysql出现死锁的必要条件:1、资源独占条件;2、请求和保持条件;3、不剥夺条件;4、相互获取锁条件。

mysql死锁是什么

本教程操作环境:windows7系统、mysql8版本、Dell G3电脑。

1、什么是死锁?

死锁指的是在两个或两个以上不同的进程或线程中,因争夺资源而造成的一种互相等待的现象;由于存在共同资源的竞争或进程(或线程)间的通讯而导致各个线程间相互挂起等待,如果没有外力作用,最终会引发整个系统崩溃。

此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等的进程称为死锁进程。

2、Mysql出现死锁的必要条件

资源独占条件

指多个事务在竞争同一个资源时存在互斥性,即在一段时间内某资源只由一个事务占用,也可叫独占资源(如行锁)。

请求和保持条件

指在一个事务a中已经获得锁A,但又提出了新的锁B请求,而该锁B已被其它事务b占有,此时该事务a则会阻塞,但又对自己已获得的锁A保持不放。

不剥夺条件

指一个事务a中已经获得锁A,在未提交之前,不能被剥夺,只能在使用完后提交事务再自己释放。

相互获取锁条件

指在发生死锁时,必然存在一个相互获取锁过程,即持有锁A的事务a在获取锁B的同时,持有锁B的事务b也在获取锁A,最终导致相互获取而各个事务都阻塞。

3、 Mysql经典死锁案例

假设存在一个转账情景,A账户给B账户转账50元的同时,B账户也给A账户转账30元,那么在这过程中是否会存在死锁情况呢?

3.1 建表语句

CREATE TABLE `account` (  `id` int(11) NOT NULL COMMENT '主键',  `user_id` varchar(56) NOT NULL COMMENT '用户id',  `balance` float(10,2) DEFAULT NULL COMMENT '余额',  PRIMARY KEY (`id`),  UNIQUE KEY `idx_user_id` (`user_id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='账户余额表';

3.2 初始化相关数据

INSERT INTO `test`.`account` (`id`, `user_id`, `balance`) VALUES (1, 'A', 80.00);INSERT INTO `test`.`account` (`id`, `user_id`, `balance`) VALUES (2, 'B', 60.00);

mysql死锁是什么

3.3 正常转账过程

在说死锁问题之前,咱们先来看看正常的转账过程。
正常情况下,A用户给B用户转账50元,可在一个事务内完成,需要先获取A用户的余额和B用户的余额,因为之后需要修改这两条数据,所以需要通过写锁(for UPDATE)锁住他们,防止其他事务更改导致我们的更改丢失而引起脏数据。
相关sql如下:

开启事务之前需要先把mysql的自动提交关闭

set autocommit=0;# 查看事务自动提交状态状态

show VARIABLES like 'autocommit';![在这里插入图片描述](https://img-blog.csdnimg.cn/a486a4ed5c9d4240bd115ac7b3ce5a39.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_

Q1NETiBA6ZqQIOmjjg==,size_20,color_FFFFFF,t_70,g_se,x_16)

# 转账sqlSTART TRANSACTION;# 获取A 的余额并存入A_balance变量:80SELECT user_id,@A_balance:=balance from account where user_id = 'A' for UPDATE;# 获取B 的余额并存入B_balance变量:60SELECT user_id,@B_balance:=balance from account where user_id = 'B' for UPDATE;# 修改A 的余额UPDATE account set balance = @A_balance - 50 where user_id = 'A';# 修改B 的余额UPDATE account set balance = @B_balance + 50 where user_id = 'B';COMMIT;

执行后的结果:

2.png

可以看到数据更新都是正常的情况

3.4 死锁转账过程

初始化的余额为:

3.png

假设在高并发情况下存在这种场景,A用户给B用户转账50元的同时,B用户也给A用户转账30元。

那么我们的java程序操作的过程和时间线如下:

1.A用户给B用户转账50元,需在程序中开启事务1来执行sql,并获取A的余额同时锁住A这条数据。

# 事务1set autocommit=0;START TRANSACTION;# 获取A 的余额并存入A_balance变量:80SELECT user_id,@A_balance:=balance from account where user_id = 'A' for UPDATE;

2.B用户给A用户转账30元,需在程序中开启事务2来执行sql,并获取B的余额同时锁住B这条数据。

# 事务2set autocommit=0;START TRANSACTION;# 获取A 的余额并存入A_balance变量:60SELECT user_id,@A_balance:=balance from account where user_id = 'B' for UPDATE;

3.在事务1中执行剩下的sql

# 获取B 的余额并存入B_balance变量:60SELECT user_id,@B_balance:=balance from account where user_id = 'B' for UPDATE;# 修改A 的余额UPDATE account set balance = @A_balance - 50 where user_id = 'A';# 修改B 的余额UPDATE account set balance = @B_balance + 50 where user_id = 'B';COMMIT;

4.png

可以看到,在事务1中获取B数据的写锁时出现了超时情况。为什么会这样呢?主要是因为我们在步骤2的时候已经在事务2中获取到B数据的写锁了,那么在事务2提交或回滚前事务1永远都拿不到B数据的写锁。

4.在事务2中执行剩下的sql

# 获取A 的余额并存入B_balance变量:60SELECT user_id,@B_balance:=balance from account where user_id = 'A' for UPDATE;# 修改B 的余额UPDATE account set balance = @A_balance - 30 where user_id = 'B';# 修改A 的余额UPDATE account set balance = @B_balance + 30 where user_id = 'A';COMMIT;

5.png

同理可得,在事务2中获取A数据的写锁时也出现了超时情况。因为步骤1的时候已经在事务1中获取到A数据的写锁了,那么在事务1提交或回滚前事务2永远都拿不到A数据的写锁。

5. 为什么会出现这种情况呢?

主要是因为事务1和事务2存在相互等待获取锁的过程,导致两个事务都挂起阻塞,最终抛出获取锁超时的异常。

6.png

3.5 死锁导致的问题

众所周知,数据库的连接资源是很珍贵的,如果一个连接因为事务阻塞长时间不释放,那么后面新的请求要执行的sql也会排队等待,越积越多,最终会拖垮整个应用。一旦你的应用部署在微服务体系中而又没有做熔断处理,由于整个链路被阻断,那么就会引发雪崩效应,导致很严重的生产事故。

4、如何解决死锁问题?

要想解决死锁问题,我们可以从死锁的四个必要条件入手。
由于资源独占条件和不剥夺条件是锁本质的功能体现,无法修改,所以咱们从另外两个条件尝试去解决。

4.1 打破请求和保持条件

根据上面定义可知,出现这个情况是因为事务1和事务2同时去竞争锁A和锁B,那么我们是否可以保证锁A和锁B一次只能被一个事务竞争和持有呢?
答案是肯定可以的。下面咱们通过伪代码来看看:

/*** 事务1入参(A, B)* 事务2入参(B, A)**/public void transferAccounts(String userFrom, String userTo) {     // 获取分布式锁     Lock lock = Redisson.getLock();     // 开启事务     JDBC.excute("START TRANSACTION;");     // 执行转账sql     JDBC.excute("# 获取A 的余额并存入A_balance变量:80n" +             "SELECT user_id,@A_balance:=balance from account where user_id = '" + userFrom + "' for UPDATE;n" +             "# 获取B 的余额并存入B_balance变量:60n" +             "SELECT user_id,@B_balance:=balance from account where user_id = '" + userTo + "' for UPDATE;n" +             "n" +             "# 修改A 的余额n" +             "UPDATE account set balance = @A_balance - 50 where user_id = '" + userFrom + "';n" +             "# 修改B 的余额n" +             "UPDATE account set balance = @B_balance + 50 where user_id = '" + userTo + "';n");     // 提交事务     JDBC.excute("COMMIT;");     // 释放锁     lock.unLock();}

上面的伪代码显而易见可以解决死锁问题,因为所有的事务都是通过分布式锁来串行执行的。

jQuery前端table插件锁定表头和锁定首列 jQuery前端table插件锁定表头和锁定首列

前端table插件,需要layui支持,很多思路都是参照layuitable实现 :smile: ,jquery直接使用版本

jQuery前端table插件锁定表头和锁定首列 78 查看详情 jQuery前端table插件锁定表头和锁定首列

那么这样就真的万事大吉了吗?

在小流量情况下看起来是没问题的,但是在高并发场景下这里将成为整个服务的性能瓶颈,因为即使你部署了再多的机器,但由于分布式锁的原因,你的业务也只能串行进行,服务性能并不因为集群部署而提高并发量,完全无法满足分布式业务下快、准、稳的要求,所以咱们不妨换种方式来看看怎么解决死锁问题。

4.2 打破相互获取锁条件(推荐)

要打破这个条件其实也很简单,那就是事务再获取锁的过程中保证顺序获取即可,也就是锁A始终在锁B之前获取。
我们来看看之前的伪代码怎么优化?

/*** 事务1入参(A, B)* 事务2入参(B, A)**/public void transferAccounts(String userFrom, String userTo) {     // 对用户A和B进行排序,让userFrom始终为用户A,userTo始终为用户B     if (userFrom.hashCode() > userTo.hashCode()) {         String tmp = userFrom;         userFrom = userTo;         userTo = tmp;     }     // 开启事务     JDBC.excute("START TRANSACTION;");     // 执行转账sql     JDBC.excute("# 获取A 的余额并存入A_balance变量:80n" +             "SELECT user_id,@A_balance:=balance from account where user_id = '" + userFrom + "' for UPDATE;n" +             "# 获取B 的余额并存入B_balance变量:60n" +             "SELECT user_id,@B_balance:=balance from account where user_id = '" + userTo + "' for UPDATE;n" +             "n" +             "# 修改A 的余额n" +             "UPDATE account set balance = @A_balance - 50 where user_id = '" + userFrom + "';n" +             "# 修改B 的余额n" +             "UPDATE account set balance = @B_balance + 50 where user_id = '" + userTo + "';n");     // 提交事务     JDBC.excute("COMMIT;"); }

假设事务1的入参为(A, B),事务2入参为(B, A),由于我们对两个用户参数进行了排序,所以在事务1中需要先获取锁A在获取锁B,事务2也是一样要先获取锁A在获取锁B,两个事务都是顺序获取锁,所以也就打破了相互获取锁的条件,最终完美解决死锁问题。

5、 如何预防死锁

阻止死锁的途径就是避免满足死锁条件的情况发生,为此我们在开发的过程中需要遵循如下原则:

1.尽量避免并发的执行涉及到修改数据的语句。
2.要求每一个事务一次就将所有要使用到的数据全部加锁,否则就不允许执行。
3.预先规定一个加锁顺序,所有的事务都必须按照这个顺序对数据执行封锁。如不同的过程在事务内部对对象的更新执行顺序应尽量保证一致。
4.每个事务的执行时间不可太长,对程序段的事务可考虑将其分割为几个事务。在事务中不要求输入,应该在事务之前得到输入,然后快速执行事务。
5.使用尽可能低的隔离级别。

6.数据存储空间离散法。该方法是指采用各种手段,将逻辑上在一个表中的数据分散的若干离散的空间上去,以便改善对表的访问性能。主要通过将大表按行或者列分解为若干小表,或者按照不同的用户群两种方法实现。
7.编写应用程序,让进程持有锁的时间尽可能短,这样其它进程就不必花太长的时间等待锁被释放。

死锁的概念:

如果一组进程中的每一个进程都在等待仅由该组进程中的其他进程才能引发的事件,那么改组进程是死锁的。

死锁的常见表现:

死锁不仅会发生多个进程中,也会发生在一个进程中。
(1)多进程死锁:有进程A,进程B,进程A拥有资源1,需要请求正在被进程B占有的资源2。而进程B拥有资源2,请求正在被进程A战友的资源1。两个进程都在等待对方释放资源后请求该资源,而相互僵持,陷入死锁。
(2)单进程死锁:进程A拥有资源1,而它又在请求资源1,而它所请求的资源1必须等待该资源使用完毕得到释放后才可被请求。这样,就陷入了自己的死锁。

产生死锁的原因:

(1)进程推进顺序不当造成死锁。
(2)竞争不可抢占性资源引起死锁。
(3)竞争可消耗性资源引起死锁。

死锁的四个必要条件(四个条件四者不可缺一):

(1)互斥条件。某段时间内,一个资源一次只能被一个进程访问。
(2)请求和保持条件。进程A已经拥有至少一个资源,此时又去申请其他资源,而该资源又正在被进程使用,此时请求进程阻塞,但对自己已经获得的资源保持不放。
(3)不可抢占资源。进程已获得的资源在未使用完不能被抢占,只能在自己使用完时由自己释放。
(4)循环等待序列。存在一个循环等待序列P0P1P2……Pn,P0请求正在被进程P1占有的资源,P1请求正在被P2占有的资源……Pn正在请求被进程P0占有的资源。

解除死锁的两种方法:

(1)终止(或撤销)进程。终止(或撤销)系统中的一个或多个死锁进程,直至打破循环环路,使系统从死锁状态中解除出来。
(2)抢占资源。从一个或多个进程中抢占足够数量的资源,分配给死锁进程,以打破死锁状态。

6、死锁场景

本文死锁场景皆为工作中遇到(或同事遇到)并解决的死锁场景,写这篇文章的目的是整理和分享,欢迎指正和补充,本文死锁场景包括:

行锁导致死锁
gap lock/next keys lock导致死锁
index merge 导致死锁
唯一索引冲突导致死锁

注:以下场景隔离级别均为默认的Repeatable Read;

1)行锁导致死锁

7.png

死锁原因详解:

1.两个事务执行过程时间上有交集,并且过程发生在两者提交之前
2.事务1更新uid=1的记录,事务2更新uid=2的记录,在RR级别,由于uid是唯一索引,因此两个事务将分别持有uid=1和2所在行的独占锁
3.事务1执行到第二条更新语句时,发现uid=2的行被锁住,进入阻塞等待锁释放;
4.事务2执行到第二条语句时发现uid=1的行被锁,同样进入阻塞
5.两个事务互相等待,死锁产生。

相应业务案例和解决方案:
该场景常见于事务中存在for循环更新某条记录的情况,死锁日志显示lock_mode X locks rec but not gap waiting(即行锁而非间隙锁),解决方案:

1.避免循环更新,优化为一条where锁定要更新的记录批量更新
2.如果非要循环更新,尝试取消事务(能接受的话),即每一条更新为一个独立的事务

2)gap lock/next keys lock导致死锁

7-2.png

8.png

9.png

死锁原因分析:

1.事务1执行delete age = 27,务2执行delete age = 31,在RR级别,操作条件不是唯一索引时,行锁会升级为next keys
lock(可以理解为间隙锁),因此事务1锁住了25到27和27到29的区间,事务2锁住了29到31的区间
2.事务1执行insert age = 30,等待事务2释放锁
3.事务2执行insert age = 28,等待事务1释放锁
4.死锁产生,死锁日志显示lock_mode X locks gap before rec insert intention waiting

解决方案:

1.降低事务隔离级别到Read Committed,该隔离级别下间隙锁降级为行锁,可以减少死锁发生的概率
2.避免这种场景- –

3)index merge导致死锁

t_user结构改造为:

10.png

11.png

12.png

死锁分析:

1.在符合场景前提的情况下(即表数据量较大,index_merge未关闭),通过explain分析update t_user where zone_id = 1 and uid = 1可以发现type是index_merge,即会用到zone_id和uid两个索引
2.上锁的过程为:

事务1:
① 锁住zone_id=1对应的间隙锁: zoneId in (1,2)
② 锁住索引zone_id=1对应的主键索引行锁id = [1,2]
③ 锁住uid=1对应的间隙锁: uid in (1, 2)
④ 锁住uid=1对应的主键索引行锁: id = [1, 3]

事务2:
① 锁住zone_id=2对应的间隙锁: zoneId in (1,2)
② 锁住索引zone_id=2对应的主键索引行锁id = [3,4]
③ 锁住uid=2对应的间隙锁: uid in (1,2)
④ 锁住uid=2对应的主键索引行锁: id = [2, 4]

1、如果两个事务上锁的顺序相反,则有一定的概率出现死锁。另外,index_merge的形式锁住了很多不符合条件的行,浪费了资源。一般死锁日志打印的信息为:

lock_mode X locks rec but not gap waiting Record lock

解决方案:创建联合索引,使执行计划只会用到一个索引。

注:

update table set name = “wea” where col_1 = 1 or col_2 = 2 ;

col_1和col_2为联合索引,遵循最左原则col_1会走索引,但col_2会对整个索引进行扫描,此时会对整个索引加锁。

【相关推荐:mysql视频教程】

以上就是mysql死锁是什么的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/277703.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
linux系统里cp是什么意思?
上一篇 2025年11月4日 15:16:40
如何用Swoole协程实现并发HTTP请求?
下一篇 2025年11月4日 15:16:44

相关推荐

  • 开源免费PHP工具 PHP开发效率提升利器

    推荐开源免费PHP开发工具以提升效率:VS Code、Sublime Text轻量高效,PhpStorm专业强大;调试用Xdebug、Kint、Ray;依赖管理选Composer;代码质量工具包括PHPStan、Psalm、PHP_CodeSniffer;数据库管理可用%ignore_a_1%MyA…

    2026年5月10日
    000
  • MySQL数据库不支持中文的解决办法

    接上一篇文章,在解决了mysql+flask环境配置问题之后,往数据库存中文字符串会报1366错误,提示不正确的字符。继而发现默认的mysql采用了latin1字符集,这种编码是不支持中文的。 如果想支持中文的话,需要设置一下mysql字符集。 众所周知utf-8是可以的,gbk也没问题,为了可扩展…

    用户投稿 2026年5月10日
    000
  • Go语言连接外部MySQL数据库:DSN配置与常见错误解析

    本文详细阐述了go语言使用`go-sql-driver/mysql`驱动连接外部mysql数据库的正确方法。重点介绍了数据源名称(dsn)的规范格式,特别是主机地址部分的配置,以避免常见的“getaddrinfow: the specified class was not found.”等网络解析错…

    2026年5月10日
    000
  • 后缀php怎么打开_php文件打开方式与运行环境搭建指南

    要打开PHP文件需根据用途选择方式:查看代码可用文本编辑器或IDE,运行则需服务器环境。推荐新手使用XAMPP、WAMP等集成环境,将文件放入htdocs目录后访问localhost;开发者可利用PHP内置服务器,命令行执行php -S localhost:8000运行;高级用户可手动配置Apach…

    2026年5月10日
    000
  • PHP动态网页数据库备份恢复_PHP动态网页MySQL数据库备份教程

    答案:PHP动态网页的MySQL数据库备份与恢复需通过定期导出SQL文件并安全存储来保障数据安全,核心方法包括使用mysqldump命令行工具实现高效灵活的自动化备份,利用phpMyAdmin图形化工具进行手动导出导入以降低操作门槛,以及通过PHP脚本调用系统命令将备份过程集成到应用中;恢复时可采用…

    2026年5月10日
    000
  • php登录怎么实现_php用户登录系统完整实现

    <blockquote>PHP用户登录系统的核心是安全验证与会话管理。首先创建POST提交的登录表单,避免敏感信息暴露;后端通过session_start()启动会话,使用trim()和htmlspecialchars()清理输入,防止XSS攻击;利用PDO预处理语句查询数据库,防止SQ…

    用户投稿 2026年5月10日
    000
  • 远程MySQL数据库连接指南:从本地PHP应用访问GCP实例数据库

    本文详细指导如何在本地php应用中连接到google cloud platform (gcp) 虚拟机实例上的远程mysql数据库。教程涵盖了数据库连接参数的配置、使用php pdo建立连接的方法、gcp环境下的网络配置要点,以及常见的安全和故障排除建议,旨在帮助开发者顺利实现跨环境的数据库通信。 …

    2026年5月10日
    000
  • 在PHP中实现MySQL数据插入时避免重复记录的策略

    本文将探讨在php应用中向mysql数据库插入数据时,如何有效避免重复记录的产生。针对当主键或唯一索引字段值已存在的情况,我们将介绍使用`insert ignore`语句的策略,以确保数据完整性并防止不必要的重复插入,从而简化数据管理逻辑。 引言:数据完整性与重复记录问题 在数据库管理中,数据完整性…

    2026年5月10日
    000
  • php实现哪些功能

    PHP是一种通用脚本语言,可用来实现广泛的功能,包括:动态Web开发:生成响应用户请求的动态 веб页面。内容管理系统(CMS):构建允许用户管理网站内容的CMS。电子商务:开发具有购物车、订单处理和支付网关集成的电子商务网站。服务器端编程:编写命令行脚本和工具。文件操作:创建、读取、写入和删除文件…

    2026年5月10日
    000
  • PHP 动态 SQL WHERE 子句构建:避免重复 AND 的策略

    本文探讨了在 php 中动态构建 sql 查询 `where` 子句时常见的“`where and`”语法错误及其解决方案。通过逐步构建条件字符串,确保第一个条件不带 `and`,后续条件正确使用 `and` 连接,从而生成符合 sql 规范的查询语句,提高代码的健壮性和可读性。 动态构建 SQL …

    2026年5月10日
    200
  • PHP中基于用户角色的页面访问控制实践

    本教程详细讲解如何在PHP应用程序中利用会话(Session)机制实现基于用户角色的页面访问控制。通过正确的session_start()调用、用户登录时的角色信息存储,以及在受保护页面进行严格的会话和角色类型检查,确保只有特定用户(如“manager”)才能访问指定页面,从而有效防止未经授权的访问…

    2026年5月10日
    100
  • php数据库触发器应用实例_php数据库自动化任务的处理

    通过MySQL触发器与PHP结合,可在数据变更时自动记录日志、校验数据及同步状态。首先创建user_log表并定义AFTER INSERT/UPDATE/DELETE触发器,记录users表的操作信息;随后使用PHP的PDO执行增删改操作,验证日志生成;接着创建BEFORE INSERT触发器限制非…

    2026年5月10日
    000
  • php数据库数据压缩处理_php数据库存储空间优化方法

    可通过启用MySQL行压缩、PHP层数据压缩、优化字段结构及分表归档策略减少存储占用。具体步骤:1. 使用InnoDB压缩表并设置KEY_BLOCK_SIZE;2. PHP中用gzcompress压缩大数据字段,存为BLOB;3. 选用更小数据类型如TINYINT,避免冗余TEXT;4. 将历史数据…

    2026年5月10日
    100
  • php数据整理怎么按日期字段分组汇总_php按日期分组统计与时间段合并技巧

    可使用SQL或PHP对数据按日期分组汇总。1、通过MySQL的DATE()、YEAR()、MONTH()函数在查询时按日、月、年分组统计;2、在PHP中遍历数组,以date(‘Y-m-d’)等格式化日期作为键进行归类;3、按周可使用date(‘o-W’…

    2026年5月10日
    000
  • php数据库如何实现全文搜索 php数据库搜索引擎的构建方法

    答案:在PHP项目中实现数据库全文搜索需利用MySQL的FULLTEXT索引功能,通过PDO预处理语句执行MATCH()…AGAINST()查询,结合PHP过滤用户输入以防止SQL注入;为提升体验可引入中文分词、权重排序、结果高亮等优化措施;数据量增长后可迁移至Elasticsearch…

    2026年5月10日
    000
  • php调用数据同步方案_php调用多数据库数据同步

    首先明确同步需求与模式,如单向、双向、定时或实时同步;接着使用PHP通过PDO连接多数据库,基于时间戳或增量ID同步变更数据,并记录同步状态;为提高可靠性,可引入消息队列、binlog解析、中间同步层及加锁机制;最后注意网络超时、分页处理、错误重试、日志记录与测试验证,确保数据一致性与系统稳定性。 …

    2026年5月10日
    000
  • php怎么安装_在云服务器上部署PHP环境的步骤

    答案:在云服务器上部署PHP环境需搭建LEMP栈(Linux+Nginx+MySQL+PHP-FPM),依次更新系统、安装Nginx、MariaDB、PHP-FPM及扩展,配置Nginx解析PHP并测试,最后通过权限控制、安全配置、防火墙和HTTPS等措施保障环境安全稳定。 在云服务器上部署PHP环…

    2026年5月10日
    000
  • 使用MySQL和PHP高效获取最热门数据条目:统计与排序实践

    本教程详细阐述如何利用mysql的聚合函数和php的mysqli扩展,高效地从数据库中查询并排序出最常出现的数据条目。文章将通过一个具体的案例,指导读者构建正确的sql查询,并结合php进行数据处理和调试,避免常见的sql语法错误和php运行时问题,从而准确获取按频率降序排列的热门数据。 在Web开…

    2026年5月10日
    000
  • SQL查询:精确判断事件过期,结合日期与时间列

    本文旨在解决数据库中事件过期判断不精确的问题,特别是当事件的过期日期和时间分别存储在不同列时。我们将探讨两种主流的sql查询策略:一种是利用逻辑运算符`or`和`and`进行分情况判断,另一种是通过合并日期和时间列为单一时间戳进行直接比较。文章将详细阐述每种方法的实现方式、适用场景及相关注意事项,确…

    2026年5月10日
    200
  • HTML表单如何实现白名单功能?怎样只允许授权用户?

    要实现%ignore_a_1%的白名单功能并确保只有授权用户操作,核心答案是必须依赖后端服务器进行严格的身份认证、会话管理、授权检查和数据验证,前端仅能提供用户体验层面的初步提示而不能保障安全;具体而言,首先通过用户身份认证(如用户名/密码或oauth)确认用户身份,服务器创建会话并返回标识符,后续…

    2026年5月10日
    800

发表回复

登录后才能评论
关注微信