使用数据库怎么实现一个订座功能

  介绍

这篇文章给大家介绍使用数据库怎么实现一个订座功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

<强>第一部分:跳过锁定/NOWAIT订座功能实现

订座在现实生活中是一种很常见的场景,比较常见的有火车票席位选择,电影院席位选择等等。那么如何实现订座功能呢?应用程序可能有很多种不同的实现方式,当然,肯定离不开数据库。这里将介绍一种纯数据库的实现方式。

设想我们有一张座位表如下:

CREATE  TABLE  seats  (   ,seat_no  INT  PRIMARY 键,   ,booked  ENUM(& # 39;是的,,,& # 39;没有# 39;),DEFAULT  & # 39;没有# 39;),引擎=InnoDB;

表中有100个席位,从0到99,例如我们要预定席位2,3,我们可以先开启事务,锁定席位:

START 事务;SELECT  *,得到seats  WHERE  seat_no 拷贝(2、3),以及booked =, & # 39;没有# 39;,FOR 更新;

选择…更新语句返回结果有如下三种情况:

1。返回成功,并且结果集包含2和3,那么说明锁定成功。我们可以之行下一步操作,等待支付完成,并更新席位状态并提交事务,订座完成。<代码>更新座位设置预定=& # 39;是的# 39;在seat_no(2、3)提交;

2。返回成功,但结果集为空,或者只包含2或3者,那么说明锁定失败。

3。很长时间不返回直到返回超时。比如席位2或3者已经被另一事务锁定,并且在等待支付完成或者发生其他情况,导致该事务一直未提交(提交)或者回滚(rollback)。返回超时默认需要等待50秒,我们可以通过修改innodb_lock_wait_timeout参数来配置合理的等待时间。超时之后返回的错误如下:<代码>错误1205 (HY000):锁等待超时超过;尝试重新启动事务代码

情况3对用户来说,意味着卡死,完全不能接受。为什么会发生等待?在InnoDB的锁系统(锁系统)中,席位2如果被一个事务上了X(写锁)锁或第九者锁(意向更新锁),那么下一个事务要对席位2上X锁或第九者锁的事务,就要等待。这是由事务本身的特性(ACID)决定的。

那么是否有一种方法避免等待以及后续可能发生的超时呢? MySQL 8.0提供的新功能跳过锁定/NOWAIT就可以。跳过锁的意思是跳过那些已经被其他事务锁定了的席位。使用如SKIP LOCKED语下句进行席位锁定,那么返回的结果集可能为空,2或3,2和3。当结果集不为空时,返回的席位即被锁定成功。

SELECT  *,得到seats  WHERE  seat_no 拷贝(2、3),以及booked =, & # 39;没有# 39;FOR  UPDATE  SKIP 锁;

NOWAIT的意思是如果碰到被其他事务锁定的席位,不等待并直接返回错误。使用如下NOWAIT语句进行席位锁定,那么返回结果集2和3,要么返回错误。

SELECT  *,得到seats  WHERE  seat_no 拷贝(2、3),以及booked =, & # 39;没有# 39;FOR  UPDATE  NOWAIT;

如果返回错误,如下:

错误3572 (HY000):不要等待锁。

如果成功锁定两个席位,通过如下语句查询锁系统的状态:

SELECT  thread_id,, object_name,, lock_type,, lock_mode,, lock_data,, lock_status 得到performance_schema.data_locks; + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + |, thread_id  |, object_name  |, lock_type  |, lock_mode  |, lock_data  | lock_status  |   + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + |,,43,|,seats , |, TABLE , |, IX , |, NULL , |, GRANTED  |   |,,43,|,seats , |, RECORD  |, X ,, |, 2,,, |, WAITING  |   |,,42,|,seats , |, TABLE , |, IX , |, NULL , |, GRANTED  |   |,,42,|,seats , |, RECORD  |, X ,, |, 2,,, |, GRANTED  |   |,,42,|,seats , |, RECORD  |, X ,, |, 3,,, |, GRANTED  |   + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - +

跳过锁还可以很方便的用来进行随机分配席位,例如我们只需要锁定两个空的席位就可以通过如下语句实现。

SELECT  *,得到seats  WHERE  booked =, & # 39;没有# 39;,LIMIT  2, FOR  UPDATE  SKIP 锁;

跳过锁定/NOWAIT功能只针对行锁(锁)记录,不包括表锁(表锁定),元数据锁(元数据锁/MDL)。因此,带锁有跳过/NOWAIT的查询语句依然可能会因为表锁或元数据库锁而阻塞。元数据锁是MySQL服务器层用来保护数据库对象的并发访问的一致性而创建的,数据库对象不仅包括表,同时包括库,函数,存储过程,触发器,事件等等。表和行锁是InnoDB存储引擎内部为了保证事务的一致性而创建的不同粒度的锁。

使用数据库怎么实现一个订座功能