Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-41989

An UPDATE that moves a row to another partition and meets a duplicate key gives ERROR 1022 instead of ERROR 1062 on MyISAM and Aria

    XMLWordPrintable

Details

    Description

      Likely cause: the fix for MDEV-36115, commit c1492f3d077e47a015c6e4c5dcd2107b803ac3f4, in ha_partition::update_row(). This is a regression.
      Since that fix, when an UPDATE cannot write a row to its new partition, the server looks up the duplicate key in the old partition.
      CS 11.4.6 at revision ef966af801afc2a07222b5df65dddd52c77431dd, which does not have that fix, gives ERROR 1062 and names the right key in all three checks.

      --source include/have_partition.inc
      CREATE TABLE t1 (id INT PRIMARY KEY, a INT) ENGINE=MyISAM PARTITION BY HASH (id) PARTITIONS 4;
      INSERT INTO t1 VALUES (1, 1), (2, 2);
      --error 0,ER_DUP_ENTRY,ER_DUP_KEY
      UPDATE t1 SET id = 2 WHERE id = 1;
      if ($mysql_errno != 1062)
      {
        --die An UPDATE on MyISAM that moves a row to another partition and meets a duplicate key gives error $mysql_errno, not 1062 ER_DUP_ENTRY
      }
      CREATE TABLE t2 (id INT PRIMARY KEY, a INT) ENGINE=Aria PARTITION BY HASH (id) PARTITIONS 4;
      INSERT INTO t2 VALUES (1, 1), (2, 2);
      --error 0,ER_DUP_ENTRY,ER_DUP_KEY
      UPDATE t2 SET id = 2 WHERE id = 1;
      if ($mysql_errno != 1062)
      {
        --die An UPDATE on Aria that moves a row to another partition and meets a duplicate key gives error $mysql_errno, not 1062 ER_DUP_ENTRY
      }
      CREATE TABLE t3 (a INT, b INT, c INT, PRIMARY KEY (a, b), UNIQUE KEY uc (a, c)) ENGINE=MyISAM PARTITION BY HASH (a) PARTITIONS 4;
      INSERT INTO t3 VALUES (1, 1, 1), (2, 2, 1);
      --error 0,ER_DUP_ENTRY,ER_DUP_KEY
      INSERT INTO t3 VALUES (1, 1, 9) ON DUPLICATE KEY UPDATE a = 2;
      GET DIAGNOSTICS CONDITION 1 @m = MESSAGE_TEXT;
      --let $ok= query_get_value(SELECT @m LIKE '%for key ''uc''%' AS ok, ok, 1)
      if (!$ok)
      {
        --die An INSERT ... ON DUPLICATE KEY UPDATE on MyISAM that moves a row to another partition and meets a duplicate on key uc does not name key uc
      }
      DROP TABLE t1, t2, t3;

      Leads to:

      CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Optimized, Clang 22.1.8-20260622) Build 05/10/2026

      mysqltest: At line 8: An UPDATE on MyISAM that moves a row to another partition and meets a duplicate key gives error 1022, not 1062 ER_DUP_ENTRY

      MyISAM gives ERROR 1022 (23000): Can't write; duplicate key in table 't1', and Aria gives the same for t2. InnoDB, and a table without partitioning, give ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'. An UPDATE that meets a duplicate in the same partition gives ERROR 1062 on all engines. Debug builds give the same result.

      With a second UNIQUE key, the third check gives ERROR 1062 (23000): Duplicate entry '2-1' for key 'PRIMARY'. No row has the PRIMARY KEY value (2, 1). The duplicate is on key uc.

      The fix for MDEV-36817 changed only InnoDB. MyISAM and Aria still give ERROR 1022, as seen in MDEV-36937.

      MySQL, the MyISAM statements of the testcase

      +--------+---------------------------------------+------------------------------------+
      | MySQL  | UPDATE t1                             | INSERT ... ON DUPLICATE KEY UPDATE |
      +--------+---------------------------------------+------------------------------------+
      | 5.5.62 | Duplicate entry '2' for key 'PRIMARY' | Duplicate entry '2-1' for key 'uc' |
      | 5.6.51 | Duplicate entry '2' for key 'PRIMARY' | Duplicate entry '2-1' for key 'uc' |
      | 5.7.44 | Duplicate entry '2' for key 'PRIMARY' | Duplicate entry '2-1' for key 'uc' |
      +--------+---------------------------------------+------------------------------------+
      MySQL 8.0.36 and 9.1.0 do not partition a MyISAM table.

      From the code it seems that ha_partition::update_row() returns on the write error before it sets m_last_part to the new partition. info(HA_STATUS_ERRKEY) and print_error() then ask the old partition for the key number. MyISAM and Aria keep that number in the handle of each partition. The old partition has no duplicate, or it has the key of an earlier error, as in the third check. InnoDB keeps the key number in the transaction, so any partition gives the right key.

      Attachments

        Issue Links

          Activity

            People

              ycp Yuchen Pei
              Roel Roel Van de Paar
              Yuchen Pei Yuchen Pei
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - Not Specified
                  Not Specified
                  Logged:
                  Time Spent - 1h
                  1h

                  Git Integration

                    Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.