-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
executor, session: refine insert unsigned bigint autoIncreID #8181
Conversation
/run-all-tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/run-all-tests |
session/session_test.go
Outdated
tk.MustExec("drop table if exists autoid") | ||
tk.MustExec("create table autoid(`auto_inc_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,UNIQUE KEY `auto_inc_id` (`auto_inc_id`))") | ||
tk.MustExec("insert into autoid values(9223372036854775808);") | ||
tk.MustQuery("select * from autoid").Check(testkit.Rows("9223372036854775808")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about insert auto values after this? e.g. insert into autid values ();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mysql> create table autoid(`auto_inc_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,UNIQUE KEY `auto_inc_id` (`auto_inc_id`));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into autoid values(9223372036854775808);
Query OK, 1 row affected (0.00 sec)
mysql> select * from autoid;
+---------------------+
| auto_inc_id |
+---------------------+
| 9223372036854775808 |
+---------------------+
1 row in set (0.00 sec)
mysql> insert into autoid values();
Query OK, 1 row affected (0.00 sec)
mysql> select * from autoid;
+---------------------+
| auto_inc_id |
+---------------------+
| 9223372036854775808 |
| 2 |
+---------------------+
2 rows in set (0.00 sec)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ID generated on the TiKV side is int64. We see the function of "func (m *Meta) GenAutoTableID(dbID, tableID, step int64) (int64, error)".
executor/insert_common.go
Outdated
recordID, err = d.ToInt64(sc) | ||
if e.filterErr(err) != nil { | ||
return types.Datum{}, errors.Trace(err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ConvertTo
checks mysql.HasUnsignedFlag
, how about:
datum, err := d.ConvertTo(sc, &c.FieldType)
if e.filterErr(err) != nil {
return types.Datum{}, err
}
recordID = datum.GetInt64()
pingcap/parser#34 is merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got a problem:
create table autoid(`auto_inc_id` bigint unsigned not null unique key auto_increment);
insert into autoid values(9223372036854775808);
insert into autoid values();
insert into autoid values(18446744073709551615);
insert into autoid values();
select * from autoid
+----------------------+
| auto_inc_id |
+----------------------+
| 9223372036854775808 |
| 9223372036854805810 |
| 18446744073709551615 |
| 30001 |
+----------------------+
4 rows in set
Time: 0.006s
This may cause by func (t *TxStructure) HInc(key []byte, field []byte, step int64) (int64, error)
session/session_test.go
Outdated
tk.MustExec("drop table if exists autoid") | ||
tk.MustExec("create table autoid(`auto_inc_id` bigint(20) NOT NULL AUTO_INCREMENT,UNIQUE KEY `auto_inc_id` (`auto_inc_id`))") | ||
tk.MustExec("insert into autoid values(9223372036854775806);") | ||
tk.MustExec("insert into autoid values();") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the test has a problem:
mysql root@127.0.0.1:test> create table autoid(`auto_inc_id` bigint(20) NOT NULL AUTO_INCREMENT,UNIQUE KEY `auto_inc_id` (`auto_inc_id`));
Query OK, 0 rows affected
mysql root@127.0.0.1:test> insert into autoid values(9223372036854775806);
Query OK, 1 row affected
mysql root@127.0.0.1:test> select auto_inc_id,_tidb_rowid from autoid
+---------------------+---------------------+
| auto_inc_id | _tidb_rowid |
+---------------------+---------------------+
| 9223372036854775806 | 9223372036854775807 |
+---------------------+---------------------+
1 row in set
mysql root@127.0.0.1:test> insert into autoid values(); # auto_id = rowid= 9223372036854775807, cause below admin check error.
Query OK, 1 row affected
mysql root@127.0.0.1:test> select auto_inc_id,_tidb_rowid from autoid
+---------------------+---------------------+
| auto_inc_id | _tidb_rowid |
+---------------------+---------------------+
| 9223372036854775807 | 9223372036854775807 |
+---------------------+---------------------+
mysql root@127.0.0.1:test> admin check table autoid;
(8003, u'autoid err:[admin:1]index:&admin.RecordData{Handle:9223372036854775807, Values:[]types.Datum{types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:9223372036854775806, b:[]uint8(nil), x:interface {}(nil)}}} != record:&admin.RecordData{Handle:9223372036854775807, Values:[]types.Datum{types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:9223372036854775807, b:[]uint8(nil), x:interface {}(nil)}}}')
mysql root@127.0.0.1:test> select count(*) from autoid;
+----------+
| count(*) |
+----------+
| 1 |
+----------+
1 row in set
mysql root@127.0.0.1:test> select count(*) from autoid use index(auto_inc_id);
+----------+
| count(*) |
+----------+
| 2 |
+----------+
1 row in set
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please address this comment @XuHuaiyu.
meta/autoid/autoid.go
Outdated
alloc.base++ | ||
log.Debugf("[kv] Alloc id %d, table ID:%d, from %p, database ID:%d", alloc.base, tableID, alloc, alloc.dbID) | ||
if alloc.isUnsigned { | ||
if uint64(alloc.base) == math.MaxUint64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!alloc.isUnsigned need this kind of check( if alloc.base == math.MaxInt64 ) too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we put this check to line204? Then we needn't do check each time Alloc
is called.
I have a question: Why |
meta/autoid/autoid.go
Outdated
@@ -137,13 +137,12 @@ func (alloc *allocator) Rebase(tableID, requiredBase int64, allocIDs bool) error | |||
if allocIDs { | |||
if alloc.isUnsigned { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You want to prevent overflow?
Should we
if uNewBase > (math.Uint64 - step) {
panic
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes,
but why we panic here? @tiancaiamao
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, maybe error or warning...
I mean, if the ID overflow, it should not be changed to math.Uint64
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is used to prevent the alloc.end
overflow.
alloc.base is checked here.
It may be reasonable to change alloc.end to math.Uint64 if it will overflow?
@tiancaiamao
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If alloc.end overflow, what will happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tiancaiamao
The result of TiDB master:
tidb> create table t(a bigint signed not null auto_increment, unique key(a));
Query OK, 0 rows affected (0.02 sec)
tidb> insert into t value(9223372036854775806);
Query OK, 1 row affected (0.00 sec)
tidb> insert into t value();
Query OK, 1 row affected (0.00 sec)
tidb> insert into t value();
Query OK, 1 row affected (0.00 sec)
tidb> insert into t value();
Query OK, 1 row affected (0.00 sec)
tidb> insert into t value();
Query OK, 1 row affected (0.00 sec)
tidb> select * from t;
+----------------------+
| a |
+----------------------+
| -9223372036854775808 |
| -9223372036854775806 |
| -9223372036854775804 |
| -9223372036854775802 |
| 9223372036854775806 |
+----------------------+
5 rows in set (0.00 sec)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overwrite the old row id is dangerous for data consistency.
Is it acceptable to change the behavior to throw error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a tradeoff, #8181 (review) may be better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think throw error is simple, easier, and more robust.
should be merged with pingcap/parser#79 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
meta/autoid/autoid.go
Outdated
} | ||
alloc.base, alloc.end = newBase, newEnd | ||
} | ||
|
||
alloc.base++ | ||
log.Debugf("[kv] Alloc id %d, table ID:%d, from %p, database ID:%d", alloc.base, tableID, alloc, alloc.dbID) | ||
log.Debugf("[kv] Alloc id %d, table ID:%d, from %p, database ID:%d", uint64(alloc.base), tableID, alloc, alloc.dbID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we remove "uint64"?
@@ -57,7 +57,7 @@ func (*testSuite) TestT(c *C) { | |||
}) | |||
c.Assert(err, IsNil) | |||
|
|||
alloc := autoid.NewAllocator(store, 1) | |||
alloc := autoid.NewAllocator(store, 1, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some tests for NewAllocator
when isUnsigned
is true. Otherwise, the test coverage of this package will decrease.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@XuHuaiyu CI failed. |
…to unsigned_autoid
/run-all-tests tidb-test=pr/651 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/run-all-tests tidb-test=pr/651 |
/run-all-tests tidb-test=pr/651 |
/run-common-tests |
/run-common-tests tidb-test=pr/651 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Refer: pingcap/parser#34
What problem does this PR solve?
Before this commit, the behavior of the following sqls in TiDB is wrong.
What is changed and how it works?
Note: After this commit, we can promise the correctness for the behavior when inserting a specific value or an auto-generated value into the auto-increment column.
BUT it is not 100% consistent with MySQL now, we :
Check List
Tests
Code changes
Side effects
none
Related changes
release-2.0 release-2.1
This change is