19 Nov 2021
数据库中的一个字段,业务开发计划将其改为自增,由DBA执行后,发现原本字段中为NULL的记录,全都按照自增规则给重新赋了值。这不符合初衷啊,是为什么呢?
docker run -it -d --name mysql -e MYSQL_EMPTY_PASSWORD=true mysql:5.7
创建测试表test2
CREATE TABLE test2 ( id INT NOT NULL, score INT NULL, PRIMARY KEY (id), INDEX (score) );
score字段,允许为NULL,用来测试;之所以给score增加索引,是因为这是增加AUTO_INCREMENT的前提。
准备测试数据
INSERT INTO test2 VALUES (1, NULL), (2, 200), (3, NULL), (4, 0), (5, -2);
测试数据涵盖范围:
- 正数
- NULL
- 0
- 负数
查看当前的现存记录
SELECT * FROM test2 ORDER BY id;
输出:
> +----+-------+ > | id | score | > +----+-------+ > | 1 | NULL | > | 2 | 200 | > | 3 | NULL | > | 4 | 0 | > | 5 | -2 | > +----+-------+ > 5 rows in set (0.01 sec) > ``` **在有现存数据的基础上,设定score字段自增** ``` sql ALTER TABLE test2 MODIFY COLUMN score INT AUTO_INCREMENT;
查看修改为自增之后的结果
SELECT * FROM test2 ORDER BY id;
输出:
+----+-------+ | id | score | +----+-------+ | 1 | 1 | | 2 | 200 | | 3 | 201 | | 4 | 202 | | 5 | -2 | +----+-------+ 5 rows in set (0.01 sec)
NULL和0值都会按照自增规则被重新赋值NULL和0值都会按照自增规则被重新赋值Specifying NULL or 0 for the AUTO_INCREMENT column In all lock modes (0, 1, and 2), if a user specifies NULL or 0 for the AUTO_INCREMENT column in an INSERT, InnoDB treats the row as if the value was not specified and generates a new value for it.
文档中着重介绍了变量innodb_autoinc_lock_mode,这个变量表示了处理AUTO_INCREMENT时的锁的模式,有可能会影响主备情况下并发事务的自增逻辑,牵扯到表锁和行锁,详细信息还是看上面的参考文档链接。
SHOW VARIABLES LIKE "innodb_autoinc_lock_mode";
输出:
+--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_autoinc_lock_mode | 1 | +--------------------------+-------+ 1 row in set (0.04 sec)
表创建好之后,增加自增逻辑,一定要慎重。如果是业务方面的需求,最好是用代码来解决自增问题,而不是依赖数据库的能力。