本文目录一览:
- 1、怎么重置mysql的自增列AUTO
- 2、mysql 自增插入
- 3、mysql中auto_increment是干什么的?
- 4、mysql自增语句
- 5、一文让你彻底弄懂MySQL自增列
- 6、在mysql中要将id设置成自增并且要在前面自动补0,应该要怎么实现啊??
怎么重置mysql的自增列AUTO
1 重建列 2 truancate 表 3 使用命令,如下: Welcome to the MySQL
monitor. Commands end with ; or \g. Your MySQL connection id is 2
Server version: 5.5.41-log MySQL Community Server (GPL) Copyright (c)
2000, 2014, Oracle and/or its affiliates. All rights reserved. Oracle
is a registered trademark of Oracle Corporation and/or its affiliates.
Other names may be trademarks of their respective owners. Type 'help;'
or '\h' for help. Type '\c' to clear the current input statement.
mysql use test Database changed alter table t2 auto_increment=10;
Query OK, 2 rows affected (0.17 sec) Records: 2 Duplicates: 0
Warnings: 0 mysql insert into t2 values(); Query OK, 1 row affected
(0.05 sec) mysql select * from t2; +----+ | id | +----+ | 1 | | 2
| | 10 | +----+ 3 rows in set (0.00 sec) mysql
mysql 自增插入
列的自增属性,一般用来设置整数列根据一定步长逐步增长的值,类似于其他数据库的序列。不过这里的“序列”是基于特定一张表的。关于自增属性的相关特性如下:
1. 控制自增属性性能的变量:innodb_autoinc_lock_mode
innodb_autoinc_lock_mode=0
代表传统模式,也就是说,在对有自增属性的字段插入记录时,会持续持有一个表级别的自增锁,直到语句执行结束为止。比如说下面两条语句,SQL 1 在执行期间,一直持有对表 f1 的表级自增锁,接下来 SQL 2 执行时锁超时。
innodb_autoinc_lock_mode=1
代表连续模式,和传统模式差不多,不同的点在于对于简单的插入语句,比如 SQL 2,只在分配新的 ID 过程中持有一个轻量级的互斥锁(线程级别,而不是事务级别),而不是直到语句结束才释放的表锁。
代表交错模式。这个模式下放弃了自增表锁,产生的值会不连续。不过这是性能最高的模式,多条插入语句可以并发执行。MySQL 8.0 默认就是交错模式。
那针对复制安全来说,以上三种模式,0 和 1 对语句级别安全,也就是产生的二进制日志复制到任何其他机器都数据都一致;2 对于语句级别不安全;三种模式对二进制日志格式为行的都安全。
2. 控制自增属性的步长以及偏移量
一般用在主主复制架构或者多源复制架构里,主动规避主键冲突。
auto_increment_increment 控制步长
auto_increment_offset 控制偏移量
3. 对于要立刻获取插入值的需求
就是说要获取一张表任何时候的最大值,应该时刻执行以下 SQL 3 ,而不是 SQL 2。SQL 2 里的函数 last_insert_id() 只获取上一条语句最开始的 ID,只适合简单的 INSERT。
4. 自增列溢出现象
自增属性的列如果到了此列数据类型的最大值,会发生值溢出。比如变更表 f1 的自增属性列为 tinyint。
SQL 2 显式插入最大值 127, SQL 3 就报错了。所以这点上建议提前规划好自增列的字段类型,提前了解上限值。
5. 自增列也可以显式插入有符号的值
那针对这样的,建议在请求到达数据库前规避掉。
mysql中auto_increment是干什么的?
MySQL的中AUTO_INCREMENT类型的属性用于为一个表中记录自动生成ID功能.
可在一定程度上代替Oracle,PostgreSQL等数据库中的sequence。
在数据库应用,我们经常要用到唯一编号,以标识记录。在MySQL中可通过数据列的AUTO_INCREMENT属性来自动生成。
可在建表时可用“AUTO_INCREMENT=n”选项来指定一个自增的初始值。
可用alter table table_name AUTO_INCREMENT=n命令来重设自增的起始值。
当插入记录时,如果为AUTO_INCREMENT数据列明确指定了一个数值,则会出现两种情况,
情况一,如果插入的值与已有的编号重复,则会出现出错信息,因为AUTO_INCREMENT数据列的值必须是唯一的;
情况二,如果插入的值大于已编号的值,则会把该插入到数据列中,并使在下一个编号将从这个新值开始递增。也就是说,可以跳过一些编号。
如果自增序列的最大值被删除了,则在插入新记录时,该值被重用。
如果用UPDATE命令更新自增列,如果列值与已有的值重复,则会出错。如果大于已有值,则下一个编号从该值开始递增。
扩展资料
在使用AUTO_INCREMENT时,应注意以下几点:
1、AUTO_INCREMENT是数据列的一种属性,只适用于整数类型数据列。
2、设置AUTO_INCREMENT属性的数据列应该是一个正数序列,所以应该把该数据列声明为UNSIGNED,这样序列的编号个可增加一倍。
3、AUTO_INCREMENT数据列必须有唯一索引,以避免序号重复(即是主键或者主键的一部分)。
4、AUTO_INCREMENT数据列必须具备NOT NULL属性。
5、AUTO_INCREMENT数据列序号的最大值受该列的数据类型约束,如TINYINT数据列的最大编号是127,如加上UNSIGNED,则最大为255。
一旦达到上限,AUTO_INCREMENT就会失效。
6、当进行全表删除时,MySQL AUTO_INCREMENT会从1重新开始编号。
这是因为进行全表操作时,MySQL(和PHP搭配之最佳组合)实际是做了这样的优化操作:先把数据表里的所有数据和索引删除,然后重建数据表。
7、如果想删除所有的数据行又想保留序列编号信息,可这样用一个带where的delete命令以抑制MySQL(和PHP搭配之最佳组合)的优化:delete from table_name where 1。
也可以用last_insert_id()获取刚刚自增过的值。
参考资料:IT专家网-MYSQL中取得最后一条记录
mysql自增语句
如果希望在每次插入新记录时,自动地创建主键字段的值。可以在表中创建一个 auto-increment 字段。MySQL 使用 AUTO_INCREMENT 关键字来执行 auto-increment 任务。默认地AUTO_INCREMENT 的开始值是 1,每条新记录递增 1。
一文让你彻底弄懂MySQL自增列
MYSQL的自增列在实际生产中应用的非常广泛,相信各位所在的公司or团队,MYSQL开发规范中一定会有要求尽量使用自增列去充当表的主键,为什么DBA会有这样的要求,各位在使用MYSQL自增列时遇到过哪些问题?这些问题是由什么原因造成的呢?本文由浅入深,带领大家彻底弄懂MYSQL的自增机制。
1. 通过auto_increment关键字来指定自增的列,并指定自增列的初始值为1。
[root@localhost][test1]Create table t(id int auto_increment ,namevarchar(10),primary key(id))auto_increment=1;
QueryOK, 0 rows affected (0.63 sec)
2. 自增列上必须有索引,将t表的主键索引删除掉,会报错
[root@localhost][test1]alter table t drop primary key;
ERROR1075 (42000): Incorrect table definition; there can be only one auto column andit must be defined as a key
3. 设定auto_increment_increment参数,可以调整自增步长,该参数有session级跟global级,在分库分表以及双主or多主的模式下比较有用。
4. 一个表上只能有一个自增列
5. Mysql5.7及以下版本,innodb表的自增值保存在内存中,重启后表的自增值会设为max(id)+1,而myisam引擎的自增值是保存在文件中,重启不会丢失。Mysql8.0开始,innodb的自增id能持久化了,重启mysql,自增ID不会丢。
首先:表中自增列的上限是根据自增列的字段类型来定的。
若设定了自增id充当主键,当达到了自增id的上限值时,会发生什么样的事情呢?还是以上面创建的 t表为例, 先回顾它的表结构:
CREATETABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) COLLATE utf8mb4_binDEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
无符号的int类型,上限是2147483647。这里我们将表的自增值设为2147483647,再插入两行数据:
[root@localhost][test1]alter table t auto_increment=2147483647;
QueryOK, 0 rows affected (0.01 sec)
Records:0 Duplicates: 0 Warnings: 0
[root@localhost][test1]insert into t(name) values ('test');
QueryOK, 1 row affected (0.01 sec)
[root@localhost][test1]insert into t(name) values ('test');
ERROR 1062 (23000): Duplicate entry '2147483647' for key 'PRIMARY'
可以看到,第一个插入没问题,因为自增列的值为2147483647,这是达到了上限,还没有超过,第二行数据插入时,则报出主键重复,在达到上限后,无法再分配新的更大的自增值,也没有从1开始从头分配,在这里表的auto_increment值会一直是2147483647。
对于写入量大,且经常删除数据的表,自增id设为int类型还是偏小的,所以我们为了避免出现自增id涨满的情况,这边统一建议自增id的类型设为unsigned bingint,这样基本可以保障表的自增id是永远够用的。
这里内容比较多,innodb是索引组织表,所以涉及到索引的知识,但这不是本文的重点,我们快速回顾索引知识:
1. Innodb索引分为主键跟辅助索引,主键即全表,辅助索引叶子节点保存主键的值,而主键的叶子节点保存数据行,中间节点存着叶子节点的路由值。
2. Innodb存储数据(索引)的单位是页,这里默认是16K,这也意味着,数据本身越小,一个页中能存数据的量越多,而检索效率不仅仅由索引的层数来决定,更是由一次能够缓存的数据量来定,也就是说数据本身越小,则一次IO能够提取到缓冲区的数据越多(OS每次IO的量是固定的4K),查询的效率越好。
其实能够理解索引的结构及索引写入插入、更新的原理,则自然就明白为何建议使用自增id。这里我直接列出使用自增id 当主键的好处吧:
1. 顺序写入,避免了叶的分裂,数据写入效率好
2. 缩小了表的体积,特别是相比于UUID当主键,甚至组合字段当主键时,效果更明显
3. 查询效率好,原因就是我上面说到索引知识的第二点。
4. 某些情况下,我们可以利用自增id来统计大表的大致行数。
5. 在数据归档or垃圾数据清理时,也可方便的利用这个id去操作,效率高。
容易出现不连续的id
有的同志会发现,自己的表中id值存在空洞,如类似于1、2、3、8、9、10这样,有的适合有想依赖于自增id的连续性来实现业务逻辑,所以会想方设法去修改id让其变的连续,其实,这是没有必要的,这一块的业务逻辑交由MySQL实现是很不理智的,表的记录小还好,要是表的数据量很大,修改起来就糟糕了。那么,为什么自增id会容易出现空洞呢?
自增id的修改机制如下:
在MySQL里面,如果字段id被定义为AUTO_INCREMENT,在插入一行数据的时候,自增值的行为如下:
1. 如果插入数据时id字段指定为0、null 或未指定值,那么就把这个表当前的
AUTO_INCREMENT值填到自增字段;
2. 如果插入数据时id字段指定了具体的值,就直接使用语句里指定的值。
根据要插入的值和当前自增值的大小关系,自增值的变更结果也会有所不同。假设,某次要插入的值是X,当前的自增值是Y。
1. 如果XY,那么这个表的自增值不变;
2. 如果X≥Y,就需要把当前自增值修改为 新的自增值 。
新的自增值生成算法是:从auto_increment_offset开始,以auto_increment_increment为步长,持续叠加,直到找到第一个大于X的值,作为新的自增值。
Insert、update、delete操作会让id不连续。
Delete、update:删除中间数据,会造成空动,而修改自增id值,也会造成空洞(这个很少)。
Insert:插入报错(唯一键冲突与事务回滚),会造成空洞,因为这时候自增id已经分配出去了,新的自增值已经生成,如下面例子:
[root@localhost][test1] select * fromt;
+----+------+
| id | name |
+----+------+
| 1| aaa |
| 2| aaa |
| 3| aaa |
| 4| aaa |
+----+------+
4 rows in set (0.00 sec)
[root@localhost][test1] selectAuto_increment from information_schema.tables where table_name='t';
+----------------+
| Auto_increment |
+----------------+
| 5 |
+----------------+
1 row in set (0.00 sec)
[root@localhost][test1] begin;
Query OK, 0 rows affected (0.00 sec)
[root@localhost][test1] insert intot(name) values('aaa');
Query OK, 1 row affected (0.00 sec)
[root@localhost][test1] select * fromt;
+----+------+
| id | name |
+----+------+
| 1| aaa |
| 2| aaa |
| 3| aaa |
| 4| aaa |
| 5| aaa |
+----+------+
5 rows in set (0.00 sec)
[root@localhost][test1] selectAuto_increment from information_schema.tables where table_name='t';
+----------------+
| Auto_increment |
+----------------+
| 6 |
+----------------+
1 row in set (0.00 sec)
[root@localhost][test1] rollback;
Query OK, 0 rows affected (0.00 sec)
[root@localhost][test1] selectAuto_increment from information_schema.tables where table_name='t';
+----------------+
| Auto_increment |
+----------------+
| 6 |
+----------------+
1 row in set (0.01 sec)
[root@localhost][test1] select * fromt;
+----+------+
| id | name |
+----+------+
| 1| aaa |
| 2| aaa |
| 3| aaa |
| 4| aaa |
+----+------+
4 rows in set (0.00 sec)
可以看到,虽然事务回滚了,但自增id已经回不到从前啦,唯一键冲突也是这样的,这里就不做测试了。
在批量插入时(insert select等),也存在空洞的问题。看下面实验:
[root@localhost][test1] select * fromt;
+----+------+
| id | name |
+----+------+
| 1| aaa |
| 2| aaa |
| 3| aaa |
| 4| aaa |
+----+------+
4 rows in set (0.00 sec)
[root@localhost][test1] selectAuto_increment from information_schema.tables where table_name='t';
+----------------+
| Auto_increment |
+----------------+
| 5 |
+----------------+
1 row in set (0.00 sec)
[root@localhost][test1] insert intot(name) select name from t;
Query OK, 4 rows affected (0.04 sec)
Records: 4 Duplicates: 0 Warnings: 0
[root@localhost][test1] select * fromt;
+----+------+
| id | name |
+----+------+
| 1| aaa |
| 2| aaa |
| 3| aaa |
| 4| aaa |
| 5| aaa |
| 6| aaa |
| 7| aaa |
| 8| aaa |
+----+------+
8 rows in set (0.00 sec)
[root@localhost][test1] selectAuto_increment from information_schema.tables where table_name='t';
+----------------+
| Auto_increment |
+----------------+
| 12 |
+----------------+
1 row in set (0.00 sec)
可以看到,批量插入,导致下一个id值不为9了,再插入数据,即产生了空洞,这里是由mysql申请自增值的机制所造成的,MySQL在批量插入时,若一个值申请一个id,效率太慢,影响了批量插入的速度,故mysql采用下面的策略批量申请id。
1. 语句执行过程中,第一次申请自增id,会分配1个;
2. 1个用完以后,这个语句第二次申请自增id,会分配2个;
3. 2个用完以后,还是这个语句,第三次申请自增id,会分配4个;
4. 依此类推,同一个语句去申请自增id,每次申请到的自增id个数都是上一次的两倍。
在对自增列进行操作时,存在着自增锁,mysql的innodb_autoinc_lock_mode参数控制着自增锁的上锁机制。该参数有0、1、2三种模式:
0:语句执行结束后释放自增锁,MySQL5.0时采用这种模式,并发度较低。
1:mysql的默认设置。普通的insert语句申请后立马释放,insert select、replace insert、load data等批量插入语句要等语句执行结束后才释放,并发读得到提升
2:所有的语句都是申请后立马释放,并发度大大提升!但是在binlog为statement格式时,主从数据会发生不一致。这一块网上有很多介绍,我不做介绍了。
在彻底了解了MYSQL的自增机制以后,在实际生产中就能灵活避坑,这里建议不要用自增id值去当表的行数,当需要对大表准确统计行数时,可以去count(*)从库,如果业务很依赖大表的准确行数,直接弄个中间表来统计,或者考虑要不要用mysql的innodb来存储数据,这个是需要自己去权衡。另外对于要求很高的写入性能,但写入量又比较大的业务,自增id的使用依然存在热点写入的问题,存在性能瓶颈,这时候可通过分库分表来解决。
在mysql中要将id设置成自增并且要在前面自动补0,应该要怎么实现啊??
随着 MySQL 8.0.16 的发布,我们为 MGR 添加了一些功能,以增强其高可用性。其中一个功能是能够在某些情况下启用已离开组的成员自动重新加入,而无需用户干预。
为了理解这个功能的好处以及如何使用它,我们将快速查看它背后的概念以及它首先存在的动机。
介绍
MGR 允许 MySQL 用户轻松管理高可用组,并完成保证系统高可用所需的所有特征,例如容错或故障检测。
MGR 中提供的基本保证之一是该组呈现给用户的是一个不可分割的整体,这意味着一旦成员加入或离开该组,该更改将立即被其他成员得知。默认情况下,组内的数据本身最终是一致的,尽管可以被修改。为了实现这种保证,MGR 使用组成员服务,以及通过一致性算法检测有冲突的事务并中止它们。MGR 的这一方面超出了本文的范围,与成员自动重新加入功能并不完全相关,本文不作赘述。
组内新成员必须符合一些条件。其中新成员需要在事务方面赶上组进度(是通过选择组内一个成员来将已处理的事务流式传输给他,在 MGR 中称为“捐赠”)。最后,只要在此“分布式恢复”过程中没有遇到任何错误,组内新成员将被声明为 ONLINE 状态。
MGR 依靠组通信层 (GCS) 来管理组。该层实现了用于解决冲突事务的一致性算法,并强制执行一些通信特性。对于实现前面提到的组的不可分割视图,这些特性至关重要,如消息的总顺序、安全传递或视图同步等。
GCS 需要能够检测组中哪些成员失效或看起来失效。一旦这些成员被检测为失效,就将其从该组中移除,以便保持该组正常使用。为此 GCS 在每个成员中引入了一个故障检测器,用于分析组内交换的消息。如果它在一段时间内没有收到来自指定成员的消息,则故障检测器将对该成员产生“怀疑”,并认为该成员可能已经失效。成员从“怀疑”到真正失效的等待时间是可以配置的。
重新加入成员存在的问题
我们已经了解 MGR 必须为了高可用提供的策略,以及它如何实现,接下来请看示例:
一个小组由三个成员组成,其中一个成员偶尔会遇到丢失数据包、断连或者其它导致无法解决的错误情况的影响组内通信。还要考虑这些错误持续时间超过 group_replication_member_expel_timeout的值。
其中一个组员发生故障,小组的其他成员将决定踢出该成员。问题是,一旦该成员重新入组,他将被组驱逐加入失败,需要通过手动干预。
如果该成员的驱逐超时属性设置不为 0,则它将在被驱逐前等待满足该时间量(将超时设置为 0 意味着他将永远等待)。超时后成员将被驱逐并重新建立连接,并且无法重新加入旧组,需要再次手动干预。
于此,当存在网络故障时,显然需要手动干预。
在 MySQL 8.0.16 中,我们引入了自动重新加入组的功能,一旦成员被驱逐出组,它就会自动尝试重新加入该组,直到达到预设的次数为止。有时每次重试之间至少等待5分钟。
如何启动自动重新加入?
可以通过将group_replication_autorejoin_tries设置为所需的重试次数来开启并使用自动重新加入功能。
SET GLOBAL group_replication_autorejoin_tries = 3
默认值为 0,表示服务器禁用自动重新加入。
如何验证自动重新加入?
与 MySQL 中的许多功能一样,自动重新加入过程是可以监测的。自动重新加入的可检测性依赖于性能模式基础架构,阶段式收集有关数据。
他们获取以下信息:
事件发生的线程ID(THREAD_ID)
活动名称(EVENT_NAME)
起止时间戳以及事件的总持续时间(TIMER_START,TIMER_END 和 TIMER_WAIT)
在事件停止之前完成的工作单位和预估工作单位(WORK_COMPLETED,WORK_ESTIMATED)
因此,当自动重新加入过程开始时,它将在performance schema中注册一个名为“stage / grouprpl / Undergoing auto-rejoinprocedure”的事件。使用表performance_schema.events_stage_current, performance_schema.events_stages_summary_global_by_event_name和performance_schema.events_stages_history_long我们可以观察到以下内容:
是否正在进行自动重新加入程序
到目前为止,已经减少重试的次数
直到下一次重试的估计剩余时间
自动重新加入过程状态
可以通过过滤包含“auto-rejoin”字符串的活动事件来查找自动重新加入过程状态(即,是否正在进行):
SELECT COUNT(*) FROM performance_schema.events_stages_current
WHERE EVENT_NAME LIKE '%auto-rejoin%';
COUNT(*)
1
查询结果存在,证明服务器上运行了自动重新加入过程。
到目前为止的重试次数
如果正在进行自动重新加入程序,我们可以通过选择阶段事件上的工作单元数来检查到目前为止尝试的重试次数:
SELECT WORK_COMPLETED FROM performance_schema.events_stages_current WHERE
EVENT_NAME LIKE '%auto-rejoin%';
WORK_COMPLETED
1
在这个例子中,到目前为止只有一次尝试。
预计到下次重试的剩余时间
在每次重新加入尝试之间,服务器将处于 5 分钟的可中断睡眠中。 重新加入尝试直到成功或失败之间的时间是无法估计的。 因此,为了粗略估计剩余时间,我们可以将到目前为止尝试的重试次数乘以 5 分钟,并减去到目前为止的阶段事件所花费的时间,以估计我们还需要多长时间:
SELECT (300.0 - ((TIMER_WAIT*10e-12) - 300.0 * num_retries)) AS time_remaining FROM
(SELECT COUNT(*) - 1 AS num_retries FROM
performance_schema.events_stages_current WHERE EVENT_NAME LIKE '%auto-rejoin%') AS T,
performance_schema.events_stages_current WHERE EVENT_NAME LIKE '%auto-rejoin%';
time_remaining
30.0
所以在这个例子中,在下一次重新加入之前还有 30 秒。注意性能模式表中的所有时间记帐都以微秒精度保持,因此我们将 TIMER_WAIT 缩放为秒。
使用自动重新加入与驱逐超时的权衡
到目前为止,在这篇文章中我们只关注自动重新加入。实际上,有两种不同的方法可以实现离开组的成员的重新加入:
设置自动重新加入尝试次数来实现自动重新加入
设置该成员的驱逐超时时间然后配合手动干预
能有延缓删除组内可疑成员,并且如果配置为足够长的驱逐超时时间,则增加了重新建立连接的机会,再次与组进行交互。
虽然这两个功能实现了相同的目标,但它们的工作方式是不同的,并且需要权衡。通过使用驱逐超时,您可以维护组中可疑的成员,其缺点是您无法添加或删除成员或选择新的主机。如果通过使用自动重新加入,该成员将不再是该组的正常组员,将保持在 superreadonly 模式,直到重新加入该组。但在此期间,重新加入成员的同步旧数据的可能性将增加。自动重新加入过程可监控,而驱逐超时不是真正可监控的。
所以,总结一下:
驱逐超时的优点
- 该成员一直在该组内
- 可能更适合足够小的网络故障
驱逐超时的缺点
- 在怀疑某个成员时,无法在该组上添加/删除成员
- 在怀疑某个成员时,无法选择新的主机
- 您无法监控此过程
自动重新加入的优点
- 该组将在没有重新加入成员的情况下运行,您可以添加/删除成员并选择新的主机
- 您可以监控该过程
自动重新加入的缺点
- 您增加了重新加入成员上过时读取的可能性
- 可能不适合足够小的网络故障
总而言之,我从启用自动重新加入中获得了什么?
通过启用自动重新加入,您可以减少对MySQL实例的手动干预的需要。您的系统
更加适应瞬间网络故障,同时满足对容错性和高可用的保证。
摘要
我们引入了一个名为group_replication_autorejoin_tries的新系统变量,允许用户设置 MGR 成员在被驱逐或与组的大多数人失去联系后尝试重新加入组的次数。
默认情况下,此自动重新加入过程处于关闭状态。它能帮助用户在面对瞬间网络故障时避免对 MGR 成员进行手动干预。