对弹簧批处理正在处理的表运行选择查询时,数据库查询挂起

时间:2019-01-26 12:38:00

标签: sql-server spring-boot spring-batch spring-jdbc

我有一个文件存储应用程序,它具有两个服务(作业服务和文件服务)作为春季启动应用程序。用户上载文件时,根据文件类型,它会通过春季批处理作业进行处理,其缩略图和预览是使用FFMpeg和/或ImageMagick生成的。然后将这些数据写入数据库(当前在Microsoft SQL Server 2017 Developer本地进行开发)。

较小的文件按预期工作,但我想通过发送一堆较大的音频和视频文件来测试应用程序,并开始刷新文件页面以查看文件是否已处理。但是,经过几次刷新后,UI停留在“加载”状态,直到春季批处理作业结束,然后按预期显示结果。

我进行了相同的测试,并检查了“网络”选项卡,并注意到为检索文件列表而进行的调用处于“待处理”状态。它一直停留在该阶段,直到其余批处理过程完成并成功返回为止(200)。

在Web服务端进行一些调试之后,我发现文件服务应用程序卡在以下行:

List<Asset> allAssets = jdbcTemplate.query("SELECT asset_id, asset_extension, asset_import_date, asset_imported_by_username, asset_name, asset_path, asset_preview_path, asset_thumbnail_path, asset_type FROM assets", new AssetRowMapper()); 

因此,在我的场景中,当我刷新文件页面时,我试图访问资产表,因为弹簧批处理作业也在同一表上工作,以插入和更新每个与文件相关的数据。我认为插入和更新查询可能会以某种方式优先,并从我的选择查询中锁定表。因此,我从资产表创建了一个视图,并将查询更改为:

List<Asset> allAssets = jdbcTemplate.query("SELECT asset_id, asset_extension, asset_import_date, asset_imported_by_username, asset_name, asset_path, asset_preview_path, asset_thumbnail_path, asset_type FROM assets_vw", new AssetRowMapper()); 

不幸的是,这没有用,我得到了相同的结果。

要查看此问题是源于应用程序端(我的代码)还是数据库端,我运行了相同的测试,但是我通过数据库上的SQL Management Studio手动运行了相同的查询。有趣的是,在几次成功的查询之后(正如我在UI上看到的那样),我得到了相同的结果,查询一直停留在“执行”阶段,直到其余的春季批处理作业完成。

所以看来问题出在数据库方面。

我检查了数据库上的最大连接数(如在各种帖子中所建议的),它已经是默认值0(无限制)。

目前,我不确定数据库(或代码)出了什么问题。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

我同意@scsimon的评论,即症状是由于阻塞所致。 SQL Server默认在READ COMMITTED隔离级别使用锁定,因此当SELECT查询(检索所有行)遇到一行尚未提交的正在进行中的上载时,很可能被阻止

请考虑打开READ_COMMITTED_SNAPSHOT数据库选项,以便在不更改应用程序代码的情况下使用行版本控制而不是锁定在READ COMMITTED隔离级别。除非您的应用程序特别依赖于锁定行为(例如,将SQL Server表用作队列时),否则这是一个可行的解决方案。 READ_COMMITTED_SNAPSHOT的其他考虑因素包括增加的tempdb使用量(用于版本存储)和每行大小增加14字节。

我要添加的是,READ_COMMITTED_SNAPSHOT在Azure SQL数据库中默认处于启用状态,但在本地版本中未启用。

答案 1 :(得分:1)

问题可能是您的大量插入操作正在单笔交易中执行。对于处理插入内容的服务,我将检查代码以确保不是这种情况。如果是这样,则不需要所有插入都为全部或全部操作。您可以将单个文件的所有插入都作为单个事务的一部分,而不是将所有文件都作为单个事务的一部分。这样可以确保来自SELECT语句的READ LOCKS有机会进入队列并得到更及时的处理。