--不指定值时,自增2到3
mysql> insert into test(ftime,ftype,fdesc) values(now(),3,'c');
Query OK, 1 row affected (0.01 sec)
mysql> select * from test;
+-----+---------------------+-------+-------+
| Fid | Ftime | Ftype | Fdesc |
+-----+---------------------+-------+-------+
| 1 | 2008-04-23 19:32:22 | 1 | a |
| 2 | 2008-04-23 19:32:41 | 2 | b |
| 3 | 2008-04-23 19:33:27 | 3 | c |
+-----+---------------------+-------+-------+
3 rows in set (0.00 sec)
--大于当前计数器值时,设为指定值100
mysql> insert into test values(100,now(),4,'d');
Query OK, 1 row affected (0.00 sec)
mysql>
mysql> select * from test;
+-----+---------------------+-------+-------+
| Fid | Ftime | Ftype | Fdesc |
+-----+---------------------+-------+-------+
| 1 | 2008-04-23 19:32:22 | 1 | a |
| 2 | 2008-04-23 19:32:41 | 2 | b |
| 3 | 2008-04-23 19:33:27 | 3 | c |
| 100 | 2008-04-23 19:34:01 | 4 | d |
+-----+---------------------+-------+-------+
--指定负数或大于精度的值(int(10) unsigned精度为0--4294967295
mysql> insert into test values(-1,now(),5,'aa');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from test;
+-----+---------------------+-------+-------+
| Fid | Ftime | Ftype | Fdesc |
+-----+---------------------+-------+-------+
| 1 | 2008-04-23 19:32:22 | 1 | a |
| 2 | 2008-04-23 19:32:41 | 2 | b |
| 3 | 2008-04-23 19:33:27 | 3 | c |
| 100 | 2008-04-23 19:34:01 | 4 | d |
| 101 | 2008-04-23 19:35:40 | 5 | aa | ==>负数时相当于没有指定,自增1
+-----+---------------------+-------+-------+
5 rows in set (0.00 sec)
mysql> insert into test values(4294967295+1,now(),5,'aa');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from test;
+------------+---------------------+-------+-------+
| Fid | Ftime | Ftype | Fdesc |
+------------+---------------------+-------+-------+
| 1 | 2008-04-23 19:32:22 | 1 | a |
| 2 | 2008-04-23 19:32:41 | 2 | b |
| 3 | 2008-04-23 19:33:27 | 3 | c |
| 100 | 2008-04-23 19:34:01 | 4 | d |
| 101 | 2008-04-23 19:35:40 | 5 | aa |
| 4294967295 | 2008-04-23 19:36:03 | 5 | aa | ==>最大值
+------------+---------------------+-------+-------+
6 rows in set (0.00 sec)
mysql> insert into test(ftime,ftype,fdesc) values(now(),3,'c');==>自增1时,发现已经超过最大值,赋值为最大值,发现id列是pk,前面已经有一个最大值,键重复!
ERROR 1062 (23000): Duplicate entry '4294967295' for key 1
mysql>
--gap演示
mysql> drop table test;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE `test` (
-> `Fid` int(10) unsigned NOT NULL auto_increment,
-> `Ftime` datetime NOT NULL default '0000-00-00 00:00:00',
-> `Ftype` int(10) unsigned NOT NULL default '0',
-> `Fdesc` varchar(255) default NULL,
-> primary key `i_fid` (`Fid`)
-> ) ENGINE=innodb DEFAULT CHARSET=latin1;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values(100,now(),4,'d');
Query OK, 1 row affected (0.01 sec)
mysql> select * from test;
+-----+---------------------+-------+-------+
| Fid | Ftime | Ftype | Fdesc |
+-----+---------------------+-------+-------+
| 100 | 2008-04-23 19:39:04 | 4 | d |
+-----+---------------------+-------+-------+
1 row in set (0.00 sec)
mysql> start transaction; ==>开始一个新事务,临时禁止了autocommit=1,相当于0,显示commit事务才生效!
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test(ftime,ftype,fdesc) values(now(),5,'aa'),(now(),5,'aa'),(now(),5,'aa'),(now(),5,'aa');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from test;
+-----+---------------------+-------+-------+
| Fid | Ftime | Ftype | Fdesc |
+-----+---------------------+-------+-------+
| 100 | 2008-04-23 19:39:04 | 4 | d |
| 101 | 2008-04-23 19:39:15 | 5 | aa |
| 102 | 2008-04-23 19:39:15 | 5 | aa |
| 103 | 2008-04-23 19:39:15 | 5 | aa |
| 104 | 2008-04-23 19:39:15 | 5 | aa |
+-----+---------------------+-------+-------+
5 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test(ftime,ftype,fdesc) values(now(),5,'aa');
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+-----+---------------------+-------+-------+
| Fid | Ftime | Ftype | Fdesc |
+-----+---------------------+-------+-------+
| 100 | 2008-04-23 19:39:04 | 4 | d |
| 105 | 2008-04-23 19:39:35 | 5 | aa | ==>没有从101开始,形成gap
+-----+---------------------+-------+-------+
2 rows in set (0.00 sec)
--create table & alter table中的AUTO_INCREMENT = n选项
mysql> CREATE TABLE `test2` (
-> `Fid` int(10) unsigned not null auto_increment ,
-> `Ftime` datetime NOT NULL default '0000-00-00 00:00:00',
-> `Ftype` int(10) unsigned NOT NULL default '0',
-> `Fdesc` varchar(255) default NULL,
-> primary key `i_fid` (`Fid`)
-> ) ENGINE=innodb DEFAULT CHARSET=latin1 AUTO_INCREMENT = 100;
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test2(ftime,ftype,fdesc) values(now(),5,'aa'),(now(),5,'aa'),(now(),5,'aa'),(now(),5,'aa');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from test2;
+-----+---------------------+-------+-------+
| Fid | Ftime | Ftype | Fdesc |
+-----+---------------------+-------+-------+
| 100 | 2008-04-23 19:41:51 | 5 | aa | ==>从100开始
| 101 | 2008-04-23 19:41:51 | 5 | aa |
| 102 | 2008-04-23 19:41:51 | 5 | aa |
| 103 | 2008-04-23 19:41:51 | 5 | aa |
+-----+---------------------+-------+-------+
4 rows in set (0.00 sec)
mysql> alter table test2 AUTO_INCREMENT = 1000;
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> insert into test2(ftime,ftype,fdesc) values(now(),5,'aa');
Query OK, 1 row affected (0.00 sec)
mysql> select * from test2;
+------+---------------------+-------+-------+
| Fid | Ftime | Ftype | Fdesc |
+------+---------------------+-------+-------+
| 100 | 2008-04-23 19:41:51 | 5 | aa |
| 101 | 2008-04-23 19:41:51 | 5 | aa |
| 102 | 2008-04-23 19:41:51 | 5 | aa |
| 103 | 2008-04-23 19:41:51 | 5 | aa |
| 1000 | 2008-04-23 19:42:48 | 5 | aa |
+------+---------------------+-------+-------+
注意:default与auto_increment不可同时使用,auto_increment列必须为pk,一个表中只能有一个auto_increment列
几个疑问:
1) 手册上讲计数器的初始化算法是由mysql执行一个类似语句来做的
SELECT MAX(ai_col) FROM T FOR UPDATE;
在my.cnf中指定log=query_log(记录下所有sql)重启mysql后,对一个空表执行insert,并没有发现类似语句
2) 手册提到在第2-(2)情况下初始化计数器时,会进行'独占性锁定读'直到事务结束
Note that in this initialization we do a normal exclusive-locking read on the table and the lock
lasts to the end of the transaction.
insert需要获得计数器上的AUTO_INC锁
怎样才能模拟这两个场景,查看到锁定了?
3) auto_increment counter是否是一个变量?
当被初始化(initialize)后,后面就是引用(refer)它,而不再需要初始化,除非mysqld死掉后重启,这个变量被重置(由于常驻内存没有放磁盘文件中),这时又需要初始化(initialize)?
只有在初始化时,才用SELECT MAX(ai_col) FROM T FOR UPDATE;算法
初始化过后,遇到insert时就是直接拿计counter+1赋值给counter及列值,而不再是从表中取最大值+1
否则,第4点关于'空隙'问题就解释不了 ---用select max()就不会存在间隙,除非人为设定!