[转载]MySQL UUID() 函数

目录

文/温国兵

一 引子

在 MySQL 中,可以有如下几种途径实现唯一值:

  • 自增序列
  • UUID() 函数
  • 程序自定义

UUID 基于 16 进制,由 32 位小写的 16 进制数字组成,如下:

aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

比如123e4567-e89b-12d3-a456-426655440000就是一个典型的 UUID。

MySQL 实现了 UUID,并且提供 UUID() 函数方便用户生成 UUID。在 MySQL 的 UUID() 函数中,前三组数字从时间戳中生成,第四组数字暂时保持时间戳的唯一性,第五组数字是一个 IEEE 802 节点标点值,保证空间唯一。使用 UUID() 函数,可以生成时间、空间上都独一无二的值。据说只要是使用了 UUID,都不可能看到两个重复的 UUID 值。当然,这个只是在理论情况下。

二 MySQL UUID() 函数

mysql -uroot -proot
mysql> SHOW VARIABLES LIKE ‘%version%‘;
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| innodb_version          | 5.5.40                       |
| protocol_version        | 10                           |
| slave_type_conversions  |                              |
| version                 | 5.5.40-log                   |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | linux2.6                     |
+-------------------------+------------------------------+
7 rows in set (0.00 sec)

mysql> SELECT UUID(), UUID(), LENGTH(UUID()), CHAR_LENGTH(UUID()) \G
*************************** 1. row ***************************
             UUID(): 19a87b1a-a298-11e4-aa3c-08002735e4a4
             UUID(): 19a87b26-a298-11e4-aa3c-08002735e4a4
     LENGTH(UUID()): 36
CHAR_LENGTH(UUID()): 36
1 row in set (0.00 sec)

mysql> SELECT UUID(), UUID(), LENGTH(UUID()), CHAR_LENGTH(UUID()) \G
*************************** 1. row ***************************
             UUID(): 450e1572-a298-11e4-aa3c-08002735e4a4
             UUID(): 450e157c-a298-11e4-aa3c-08002735e4a4
     LENGTH(UUID()): 36
CHAR_LENGTH(UUID()): 36
1 row in set (0.00 sec)

可以看到,同一个 SQL 语句中,多处调用 UUID() 函数得到的值不相同。也就是说每次调用 UUD 函数都会生成一个唯一的值。并且多次调用或执行得到的后两组值相同。另外,本身 UUID 是 32 位,因为 MySQL 生成的 UUID 有四个中划线,所以在 utf8 字符集里,长度为 36 位。

我们关闭 MySQL,然后启动。

/etc/init.d/mysqld stop
Shutting down MySQL.                                       [  OK  ]

/etc/init.d/mysqld start
Starting MySQL..                                           [  OK  ]

再次调用 UUID() 函数。

mysql> SELECT UUID(), UUID(), LENGTH(UUID()), CHAR_LENGTH(UUID()) \G
*************************** 1. row ***************************
             UUID(): 586546b2-a298-11e4-b0fc-08002735e4a4
             UUID(): 586546c5-a298-11e4-b0fc-08002735e4a4
     LENGTH(UUID()): 36
CHAR_LENGTH(UUID()): 36
1 row in set (0.00 sec)

可以看到,第四组的值与重启之前发生变化,直到下一次重启 MySQL。

我们连接到另一台服务器,再次调用 UUID() 函数。

mysql> SELECT UUID(), UUID(), LENGTH(UUID()), CHAR_LENGTH(UUID()) \G
*************************** 1. row ***************************
             UUID(): 8fa81275-a298-11e4-8302-0800276f77f9
             UUID(): 8fa81291-a298-11e4-8302-0800276f77f9
     LENGTH(UUID()): 36
CHAR_LENGTH(UUID()): 36
1 row in set (0.00 sec)

可以看到跟之前的数据不同,包括第五组数据。因为第五组的值跟机器相关,所以,同一台机器第五组值不变,不同机器则变。

三 复制中的 UUID()

3.1 实验环境介绍

主机 IP地址 主机名 备注
rhel-01: 10.10.2.231 rhel-01 master
rhel-02: 10.10.2.227 rhel-02 slave

操作系统版本:RHEL 6.5

所需要的软件包:mysql-5.5.40-linux2.6-x86_64.tar.gz

3.2 搭建复制环境

在此不赘述,请参考:MySQL AB 复制

3.3 基于 STATEMENT 模式

rhel-01 中做如下设置,设置为 STATEMENT 模式。

mysql> SET tx_isolation="REPEATABLE-READ";
Query OK, 0 rows affected (0.00 sec)

mysql> SET binlog_format="STATEMENT";
Query OK, 0 rows affected (0.00 sec)

rhel-02 也做如下设置:

mysql> SET tx_isolation="REPEATABLE-READ";
Query OK, 0 rows affected (0.00 sec)

mysql> SET binlog_format="STATEMENT";
Query OK, 0 rows affected (0.00 sec)

rhel-01 创建测试表,插入测试数据。在插入数据之后,还可以看到一个警告。

mysql> USE test;
Database changed
mysql> CREATE TABLE user
    -> (name VARCHAR(36),
    -> en_name VARCHAR(20),
    -> job VARCHAR(10),
    -> addr VARCHAR(20)
    -> ) DEFAULT CHARSET=utf8 ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO user(name, en_name, job, addr) VALUES(UUID(), "robin", "dba", "GZ");
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
| Level | Code | Message |
+-------+------+-----------------------------------------------------+
| Note  | 1592 | Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. |
+-------+------+-----------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM user \G
*************************** 1. row ***************************
   name: 24d785a2-a29c-11e4-b0fc-08002735e4a4
en_name: robin
    job: dba
   addr: GZ
1 row in set (0.00 sec)

rhel-02 查看复制的数据。

mysql> USE test;
Database changed

mysql> SELECT * FROM user \G
*************************** 1. row ***************************
   name: 24cd38fe-a29c-11e4-8302-0800276f77f9
en_name: robin
    job: dba
   addr: GZ
1 row in set (0.00 sec)

可以看到,rhel-01 中的 UUID 值为24d785a2-a29c-11e4-b0fc-08002735e4a4,rhel-02 中的值为 24cd38fe-a29c-11e4-8302-0800276f77f9,两个值居然不相同,亦即主从不一致。那这样的复制是没有什么意义的。因为 UUID() 函数属于不确定函数,所以不支持 STATEMENT 模式。

3.4 基于 MIXED 模式

rhel-01 中做如下设置,设置为 MIXED 模式。

mysql> SET binlog_format="MIXED";
Query OK, 0 rows affected (0.00 sec)

rhel-02 中做如下设置:

mysql> SET binlog_format="MIXED";
Query OK, 0 rows affected (0.00 sec)

rhel-01 插入测试数据。

mysql> INSERT INTO user(name, en_name, job, addr) VALUES(UUID(), "Wentasy", "dba", "GZ");
Query OK, 1 row affected (0.06 sec)

mysql> SELECT * FROM user \G
*************************** 1. row ***************************
   name: 24d785a2-a29c-11e4-b0fc-08002735e4a4
en_name: robin
    job: dba
   addr: GZ
*************************** 2. row ***************************
   name: 8dc2c93c-a29c-11e4-b0fc-08002735e4a4
en_name: Wentasy
    job: dba
   addr: GZ
2 rows in set (0.00 sec)

rhel-02 查看复制的数据。可以看到 MIXED 模式下,两台服务器的 UUID 相同,亦即主从一致。

mysql> SELECT * FROM user \G
*************************** 1. row ***************************
   name: 24cd38fe-a29c-11e4-8302-0800276f77f9
en_name: robin
    job: dba
   addr: GZ
*************************** 2. row ***************************
   name: 8dc2c93c-a29c-11e4-b0fc-08002735e4a4
en_name: Wentasy
    job: dba
   addr: GZ
2 rows in set (0.00 sec)

3.5 基于 ROW 模式

rhel-01 中做如下设置,设置为 ROW 模式。

mysql> SET binlog_format="ROW";
Query OK, 0 rows affected (0.00 sec)

rhel-02 也做如下设置,
bash mysql> SET binlog_format="ROW"; Query OK, 0 rows affected (0.00 sec)

rhel-01 插入测试数据。

mysql> INSERT INTO user(name, en_name, job, addr) VALUES(UUID(), "dbarobin", "dba", "GZ");
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM user \G
*************************** 1. row ***************************
   name: 24d785a2-a29c-11e4-b0fc-08002735e4a4
en_name: robin
    job: dba
   addr: GZ
*************************** 2. row ***************************
   name: 8dc2c93c-a29c-11e4-b0fc-08002735e4a4
en_name: Wentasy
    job: dba
   addr: GZ
*************************** 3. row ***************************
   name: d8123587-a29c-11e4-b0fc-08002735e4a4
en_name: dbarobin
    job: dba
   addr: GZ
3 rows in set (0.00 sec)

rhel-02 查看复制的测试数据。

mysql> SELECT * FROM user \G
*************************** 1. row ***************************
   name: 24cd38fe-a29c-11e4-8302-0800276f77f9
en_name: robin
    job: dba
   addr: GZ
*************************** 2. row ***************************
   name: 8dc2c93c-a29c-11e4-b0fc-08002735e4a4
en_name: Wentasy
    job: dba
   addr: GZ
*************************** 3. row ***************************
   name: d8123587-a29c-11e4-b0fc-08002735e4a4
en_name: dbarobin
    job: dba
   addr: GZ
3 rows in set (0.00 sec)

可以看到,在 ROW 模式下,复制的数据和主服务器相同,亦即主从一致。

四 UUID_SHORT() 函数

在 MySQL 5.1 之后的版本,提供 UUID_SHORT() 函数,生成一个 64 位无符号整数。另外,需要注意的是,server_id 的范围必须为 0-255,并且不支持 STATEMENT 模式复制。

mysql> SELECT UUID_SHORT();
+-------------------+
| UUID_SHORT()      |
+-------------------+
| 95914352036544514 |
+-------------------+
1 row in set (0.00 sec)

五 小结

  • 同一个 SQL 语句中,多处调用 UUID() 函数得到的值不相同,多次调用或执行得到的后两组值相同。
  • 同一台服务器,重启 MySQL 前后的 UUID() 第四组值发生变化,第五组值不变;
  • MySQL 中,utf8 字符集下,生成的 UUID 长度为 36 位;
  • 不同机器生成的 UUID 不同,包括第五组值;
  • 在复制环境中,使用到 UUID() 函数,则一定要使用基于行或者基于混合模式复制方式。

六 Ref

–EOF–

版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)

时间: 2024-10-19 21:27:08

[转载]MySQL UUID() 函数的相关文章

MySQL UUID函数的详解(转)

MySQL UUID函数的详解 MySQL中可以有二类用于生成唯一值性质的工具:UUID()函数和自增序列,那么二者有何区别呢?我们就此对比下各自的特性及异同点: l  都可以实现生成唯一值的功能: l  UUID是可以生成时间.空间上都独一无二的值:自增序列只能生成基于表内的唯 一值,且需要搭配使其为唯一的主键或唯一索引: l  实现方式不一样,UUID是随机+规则组合而成的,而自增序列是控制一个值逐步增长的: l  UUID产生的是字符串类型值,固定长度为:36个字符,而自增序列产生的是整数

Mysql的函数使用方法

今天有点临时需求要计算一张表的结果,不想写代码,想到了mysql的自定义函数.碰到了很多问题,为了方便一下使用,在此记录一下. 需求:一张表中,有比分,需要查询出比赛id和比赛结果. 分析: 单表查询没啥的,困难就困难在怎么判断比分之后返回想要的结果. 这里我把比赛结果分别定义代号,1主场胜.2平局.3客场胜 函数逻辑: 接收两个参数,判断参数的大小,分别返回结果. 实现: Navicat操作: navicat for mysql 工具内--创建函数 这里分别是存储过程和函数,我们选择函数 设置

MySQL字符串函数、日期时间函数

MySQL字符串函数.日期时间函数 一.常见字符串函数: 1.CHAR_LENGTH  获取长度(字符为单位) 2.FORMAT  格式化 3.INSERT  替换的方式插入 4.INSTR  获取位置 5.LEFT/RIGHT  取左.取右 6.LENGTH   获取长度(字节为单位) 7.LTRIM/RTRIM/TRIM 去空格(左/右/自定义) 8.STRCMP  字符串比较 9.CONCAT  字符串拼接 10.SUBSTRING  字符串截取 1.CHAR_LENGTH:获取长度(字符

Mysql字符串函数FIND_IN_SET()的两点用法

概要:该可以查询用逗号分割的字段,以及对结果进行强制排序 首先看一张表: colid vyear area cast ,31,32,21,12 2014 1 15 ,32,33,34,35,21, 2014 2 16 ,33,34,36,39,40 2011 3 17 表中的colid字段的值是以逗号分割, 当我们需要查询这张表中,colid含有32的行, 那么可以用FIND_IN_SET() SQL如下: SELECT * FROM table WHERE FIND_IN_SET('32',

MySQL数据处理函数

数据处理函数 有时从数据库表中获取到的数据需要进行一些处理.如将小写字母替换为相应的大写字母.这个处理过程可以在客户机上进行,也可以在数据库上进行.数据库上进行会更高效.数据库中有相应的数据处理函数来处理这些数据,但是在SQL中使用特殊的数据处理函数会降低其可移植性.不同的DBMS系统,其数据处理函数不同. 大多数的SQL支持以下类型的函数 用于处理文本串的函数,如删除.填充值.转换大小写: 用于在数值数据上进行算术操作的函数: 用于处理日期和时间值并从这些值中提取特殊成分,如两个日期只差的函数

MySQL四舍五入函数ROUND(x)、ROUND(x,y)和TRUNCATE(x,y)

MySQL四舍五入函数ROUND(x) ROUND(x)函数返回最接近于参数x的整数,对x值进行四舍五入. 实例: 使用ROUND(x)函数对操作数进行四舍五入操作.SQL语句如下: mysql>SELECT ROUND(-2.34),ROUND(-4.56),ROUND(2.34),ROUND(4.56); ROUND(x)函数的执行结果如下图所示: 上图中代码执行的结果显示,进行四舍五入处理以后,只保留了各个值的整数部分. MySQL四舍五入函数ROUND(x,y) ROUND(x,y)函数

mysql 创建函数ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_f

mysql 创建函数的时候 报错 ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)ERROR 1418 (HY000

<转载> MySQL 性能优化的最佳20多条经验分享 http://www.jb51.net/article/24392.htm

当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能.这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库.希望下面的这些优化技巧对你有用. 1. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存.这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的.当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直接访问缓存结果了. 这里最主要

MySQL的几种表外连接及PHP操作MySQL的函数

内连接 按照条件,将左表的每天记录匹配右表,如果条件符合,字段内容将会被保存,如果不符合,则不会被保存: 语法: select  *|字段列表 from 左表 inner join 右表 on 左表.字段=右表.字段...; Inner 可以省略掉: 简约版语法 select  *|字段列表 from 左表 join 右表 on 左表.字段=右表.字段....; 外连接 左外连接 语法: select  *|字段列表 from 左表 left  join 右表 on 左表.字段=右表.字段...