这更像是一个“请确认/纠正我的理解”的问题。
背景 我使用 JDBC 连接到 MySQL,连接池有大约 250 个连接,其中大多数连接即使在查询终止后也似乎持续连接 - 全部使用相同的用户帐户。我希望使用临时表的存储过程由 Java 代码调用,并对 JSON 列执行转换,将其转换为不同表的行。该转换相对昂贵,可能会在数千行上执行,因此我不希望多次执行该转换。为了解决这个问题,我建议的解决方案是将数据转换为临时表,围绕现在转换的数据执行统计查询,然后将其批量插入到目标表中。
问题 我读过临时表绑定到User。我的理论是否正确,因为连接似乎从未终止并且都使用相同的用户帐户,所以在过程中创建的临时表将在所有连接和查询之间共享(因此数据可以由运行该连接的其他连接访问)同时执行相同的程序)?
限制 我想要做的是要么传输原始数据,要么执行转换并将该数据传输回 Java。然而,我们每次处理大约几百兆字节的数据,并且数据传输回 Java 似乎会锁定数据库,直到完成传输。(我不确定为什么,如果有人有解决这个问题的建议,请告诉我)
因此,我唯一能想到的其他解决方案是不传输源数据,而是执行转换,收集我需要的聚合数据,然后将转换后的数据插入到目标,而无需离开数据库服务器。
提前致谢
这就是连接池的全部目的:保持连接打开并允许应用程序重用它们,而不是经历建立新连接的昂贵过程。
根据文档,“[a]
TEMPORARY
表仅在当前会话中可见”。这意味着,不,由一个连接创建的临时表不会在所有连接之间共享。但是,当另一个应用程序从池中获取连接时,它将看到迄今为止在与该连接对应的会话中创建的任何临时表。临时表绑定到特定会话,而不是用户。在 MySQL 中,同一用户可能同时有多个会话处于活动状态。其中每一个都可以有一个同名的临时表,但没有一个可以在自己的会话之外看到任何其他表。这样一来,它就像函数中的局部变量一样。
连接由连接池保持打开状态,但获取给定连接的后续客户端看不到早期客户端留下的临时表。
当客户端从连接池请求新连接时,默认情况下,池实现会重置连接状态。这意味着 MySQL 会话会清除所有与会话相关的数据,例如事务、会话变量、临时表和准备好的语句。
https://github.com/mysql/mysql-connector-j/blob/release/8.x/src/main/user-impl/java/com/mysql/cj/jdbc/MysqlPooledConnection.java#L125-L127
这是有道理的,这是一件好事,因为否则从连接池请求连接的客户端可以查看该连接的前一个客户端留下的数据。这会产生私人数据从一个客户端泄露到另一个客户端的风险。
我所知道的所有连接池实现多年来都使用了这种连接重置功能。我相信一些连接器几年前未能做到这一点,但现已修复。如果您仍在使用不重置连接的连接池,则应停止使用它并切换到更现代的实现。
CREATE TEMPORARY TABLE
对您的任务来说不安全。我可以建议创建一个“永久”表来保存处理后的数据。然后设计一些机制(可能通过另一个永久表)来说明哪个表处理了哪些数据。
某种校验和或散列可用于唯一地标识数据集。这可能是
PRIMARY KEY
包含已处理数据的数据。