You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MariaDB中为何出现违反唯一约束的两行重复数据?

MariaDB唯一约束失效调试问题

我用JavaScript编写了一个应用程序,通过连接MariaDB服务器向两张表插入数据。首次运行程序时,房产表(property)和价格表(property_price)应保持1:1对应关系:一张表存储模拟房产数据,另一张存储价格数据,每个房产初始对应一条价格记录。后续价格变更时,一条房产可对应多条价格记录,但首次运行时绝对不应出现重复,且数据不能违反唯一索引——但目前确实出现了违反情况。

我怀疑是MariaDB配置或约束定义存在问题,以下是建表代码:

drop table if exists property_price;
drop table if exists property;

create table property
(
  unique_id bigint unsigned not null auto_increment primary key,
  web_id bigint unsigned not null,
  url varchar(256),
  street_address varchar(256),
  address_country varchar(64),
  property_type varchar(64),
  num_bedrooms int,
  num_bathrooms int,
  created_datetime datetime not null,
  modified_datetime datetime not null
);

create table property_price
(
  property_unique_id bigint unsigned not null,
  price_value decimal(19,2) not null,
  price_currency varchar(64) not null,
  price_qualifier varchar(64),
  added_reduced_ind varchar(64),
  added_reduced_date date,
  created_datetime datetime not null
);

alter table property_price
add constraint fk_property_unique_id foreign key(property_unique_id)
references property(unique_id);

alter table property
add constraint ui_property_web_id
unique (web_id);

alter table property
add constraint ui_url
unique (url);

alter table property_price
add constraint ui_property_price
unique (property_unique_id, price_value, price_currency, price_qualifier, added_reduced_ind, added_reduced_date);

当前现象:

  • DBeaver查询显示property_price表存在两条完全相同的行(截图如下)
  • 唯一约束并非完全失效:再次运行应用时,会因尝试插入已存在的重复行而失败(但不是截图中的这组重复行)

DBeaver查询到重复行

调试建议

  • 确认唯一约束的实际定义:执行show create table property_price;,检查输出中的ui_property_price约束是否包含所有指定字段,确认字段类型、排序规则是否与表定义一致,避免因字段遗漏或类型不匹配导致约束不生效。
  • 排查数据的隐性差异:不要仅依赖可视化展示,执行以下SQL查看重复行的实际字节内容,排查是否存在不可见字符(如空格、换行符、全角/半角差异):
    SELECT 
      property_unique_id, 
      price_value, 
      price_currency, 
      price_qualifier, 
      added_reduced_ind, 
      added_reduced_date,
      HEX(price_qualifier) AS qualifier_hex,
      HEX(added_reduced_ind) AS ind_hex
    FROM property_price 
    WHERE property_unique_id = [重复行的unique_id];
    
  • 检查应用插入逻辑:
    • 确认首次运行时,是否对同一个房产执行了多次价格插入操作,比如异步请求未做去重、事务未正确控制导致重复提交。
    • 验证插入价格时是否正确获取了房产的unique_id,是否存在重复使用同一ID插入多次的情况。
  • 验证事务隔离级别:执行SELECT @@tx_isolation;,若隔离级别为READ UNCOMMITTED,可能导致并发插入时约束检查失效,建议调整为MariaDB默认的REPEATABLE READ。
  • 确认存储引擎:执行SHOW TABLE STATUS LIKE 'property_price';,确保使用的是InnoDB引擎(MyISAM不支持事务级约束检查和外键)。
  • 开启SQL日志排查操作:临时开启通用日志记录所有SQL操作,执行:
    SET GLOBAL general_log = 1;
    SET GLOBAL log_output = 'table';
    
    重新运行应用后,查询mysql.general_log表,查看插入阶段的SQL语句,确认是否存在重复执行的插入请求。

内容的提问来源于stack exchange,提问作者user2138149

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 10:05:29