【问题标题】:MySQL BIGINT inconsistent for inserts?MySQL BIGINT 插入不一致?
【发布时间】:2021-05-06 07:46:30
【问题描述】:

在 ubuntu 上运行 MySQL v 5.6。 创建了一个 python 程序来执行我的所有操作。

我的应用动态创建表格。有许多。有几个非常相似。例如,这里有两个:

create table tst.intgn_party_test_load (
  party_id bigint unsigned NOT NULL,
  party_supertype varchar(15) NOT NULL,
  carrier_party_id bigint unsigned NOT NULL,
  full_name varchar(500),
  lda_actv_ind integer,
  lda_file_id integer,
  lda_created_by varchar(100),
  lda_created_on datetime,
  lda_updated_by varchar(100),
  lda_updated_on datetime, 
  PRIMARY KEY(party_id,party_supertype,carrier_party_id)
) 

create table tst.intgn_party_relationship (
  parent_party_id bigint unsigned NOT NULL,
  child_party_id bigint unsigned NOT NULL,
  relationship_type varchar(10),
  lda_actv_ind integer,
  lda_file_id integer,
  lda_created_by varchar(100),
  lda_created_on datetime,
  lda_updated_by varchar(100),
  lda_updated_on datetime, 
  PRIMARY KEY(parent_party_id,child_party_id,relationship_type)
) 

我的程序还动态填充表格。我使用转换为 BIGINT 的源数据构建派对 ID 字段。 比如它为第一个表构造的插入是:

INSERT INTO intgn_party_test_load (
  party_supertype, 
  carrier_party_id, 
  party_id, 
  full_name, 
  lda_actv_ind, 
  lda_file_id) 
SELECT  
  'Agency' as s0,
  0 as s1,
  CONV(SUBSTRING(CAST(SHA(CONCAT(full_name,ga)) AS CHAR), 1, 16), 16, 10) as s2,
  CONCAT(full_name,'-',ga) as s3, 
  lda_actv_ind, 
  lda_file_id 
FROM tst.raw_listing_20210118175114 
ON DUPLICATE KEY 
UPDATE  
  full_name = VALUES(full_name), 
  lda_actv_ind = VALUES(lda_actv_ind), 
  lda_file_id = VALUES(lda_file_id) ;

对于第二个表,插入构造看起来非常相似,并且基于完全相同的源数据:

INSERT INTO tst.intgn_party_relationship (
  parent_party_id,
  relationship_type,
  child_party_id, 
  lda_actv_ind, 
  lda_file_id) 
SELECT (Select party_id 
        from intgn_party 
        where full_name = 'xxx') as s0,
       'Location' as s1,
       CONV(SUBSTRING(CAST(SHA(CONCAT(full_name,ga)) AS CHAR), 1, 16), 16, 10) as s2, 
       lda_actv_ind, 
       lda_file_id 
FROM tst.raw_listing_20210118175114 
ON DUPLICATE KEY 
UPDATE  
  lda_actv_ind = VALUES(lda_actv_ind), 
  lda_file_id = VALUES(lda_file_id) 

现在...第一个表 (intgn_party_test_load) 是问题所在。我可以删除它,甚至手动重新创建它。无论我做什么,通过 python 插入其中的数据都将 BIGINT party_id 截断为 16 位。 使用完全相同的公式填充party_id 的每个其他表都会创建长度在 18 到 20 位之间的 BIGINT 数字。我可以看到表中加载了所有相同的源记录,并且我在第一个表 (intgn_party_test_load) 中看到了截断的值。例如,第一个表有一条记录,派对 id = 7129232523783260。第二个表(和许多其他表)有相同的记录,加载了 [child]party id = 7129232523783260081

完全相同的公式,在 python 中以完全相同的方式执行。但这个表的 BIGINT 更短。

有趣的是,我尝试手动运行插入到这个表中(不使用 python 程序),它插入了完整的 BIGINT 值。 所以我很困惑为什么 python 程序“选择”这个表不能正常工作,而它在所有其他表上都可以正常工作。

是否存在一些值被截断的奇怪情况? 顺便说一句,我的 python 程序利用 sqlalchemy 来运行创建/插入。由于它是手动工作的,我不得不假设它与 sqlalchemy 相关.. 但不知道为什么它适用于除了这张表之外的所有内容..

[编辑] 补充一下,通过sqlalchemy执行的sql命令使用db_connection.execute(sql)执行

[编辑 - 添加更多代码细节]

from sqlalchemy import create_engine, exc

engine = create_engine(
            connection_string,
            pool_size=6, max_overflow=10, encoding='latin1', isolation_level='AUTOCOMMIT'
        )
        connection = engine.connect()

sql = "INSERT INTO intgn_party_test_load (
  party_supertype, 
  carrier_party_id, 
  party_id, 
  full_name, 
  lda_actv_ind, 
  lda_file_id) 
SELECT  
  'Agency' as s0,
  0 as s1,
  CONV(SUBSTRING(CAST(SHA(CONCAT(full_name,ga)) AS CHAR), 1, 16), 16, 10) as s2,
  CONCAT(full_name,'-',ga) as s3, 
  lda_actv_ind, 
  lda_file_id 
FROM tst.raw_listing_20210118175114 
ON DUPLICATE KEY 
UPDATE  
  full_name = VALUES(full_name), 
  lda_actv_ind = VALUES(lda_actv_ind), 
  lda_file_id = VALUES(lda_file_id) ;"

        result = db_connection.execute(sql)

最好我也可以减少它(代码要复杂得多,因为它会在其他事物中动态创建语句).. 但是从我的日志记录中,我看到了它正在执行的确切语句(如上所述),并且我之后在 BIGINT 列中查看结果。除此以外的所有表。只有通过应用程序。 所以即使通过应用程序也不会发生在其他表上..

非常令人困惑.. 希望有人知道 mySQL 5.6 中围绕 BIGINT 的一个错误,因为它可能与目标表的键构造或记录的总长度有关.. 或其他一些疯狂的原因。我确实看到了这一点,有趣的是,如果我在 BIGINT 列上做一个大于 18 位长度的 distinct,它会以 16 位返回 - 猜测 distinct 函数不支持 BIGINT .. 有点希望这暗示了一个问题,但我不明白为什么其他表可以正常工作......

[编辑 - 添加一些我看到 sqlalchemy 显然在运行的东西,围绕我的查询的实际运行......只是在疯狂的情况下,它们会影响任何东西 - 对于一个表? ]

SET AUTOCOMMIT = 0
SET AUTOCOMMIT = 1
SET NAMES utf8mb4
SHOW VARIABLES LIKE 'sql_mode'
SHOW VARIABLES LIKE 'lower_case_table_names'
SELECT VERSION()
SELECT DATABASE()
SELECT @@tx_isolation
show collation where `Charset` = 'utf8mb4' and `Collation` = 'utf8mb4_bin'
SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin AS anon_1
ROLLBACK
SET NAMES utf8mb4

很难说顺序或类似的东西..有很多在同一微秒内运行。

【问题讨论】:

  • 只是添加.. 你会注意到我根本没有处理我的 python 代码中的数据类型.. SQL 语句在服务器上执行,所以我不*认为sqlalchemy 甚至知道我是否在处理 BIGINT。但是为什么完全相同的语句通过它运行不同,然后当我直接在数据库上运行时?
  • 您是否有任何可能被回滚的事务?使用INT键在同一张表中是否有同样的问题?
  • 我不能使用 INT 键,因为它们对于我的唯一性公式来说不够大。不确定回滚问题..我可以删除表并重新创建它。我开始考虑用 varchar 替换所有 BIGINT 列,并且每次都进行转换(将 BIGINT 的转换添加到插入中的 varchar).. 回去更改所有表只是头疼.. 我可以'想不出为什么我不只是改变它们的原因......回避这个问题......
  • 注意上面例子中的party id公式是“CONV(SUBSTRING(CAST(SHA(CONCAT(full_name,ga)) AS CHAR), 1, 16), 16, 10) as s2" -- 它需要两列,将它们连接起来,然后使用 SHA 将其转换为数字..
  • 由于您只是通过Python运行代码时遇到问题,因此您需要发布相关的Python代码。

标签: python mysql sqlalchemy bigint


【解决方案1】:

在绞尽脑汁数天之后.. 从各个角度来看,我无法弄清楚为什么许多表中有一张在截断 SHA 值时存在问题。 最后,我重新设计了我持有我的身份的方式,我不再费心转换为 BIGINT。当我将其保留为 CHAR 时,一切正常。

CAST(SHA(CONCAT(full_name,ga)) AS CHAR)

因此将我所有的 Id 列更改为 varchar(40) 并使用上述样式。现在一切都好。连接将使用 varchar 而不是 bigint - 我可以接受。

【讨论】:

    猜你喜欢
    • 2017-07-31
    • 2011-07-13
    • 2020-11-08
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 2018-08-11
    • 2021-05-23
    • 2020-06-11
    相关资源
    最近更新 更多