文/温国兵
html
在 MySQL 中,能够有以下几种途径实现惟一值:mysql
UUID 基于 16 进制,由 32 位小写的 16 进制数字组成,以下:linux
aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeeesql
好比123e4567-e89b-12d3-a456-426655440000
就是一个典型的 UUID。bash
MySQL 实现了 UUID,而且提供 UUID() 函数方便用户生成 UUID。在 MySQL 的 UUID() 函数中,前三组数字从时间戳中生成,第四组数字暂时保持时间戳的惟一性,第五组数字是一个 IEEE 802 节点标点值,保证空间惟一。使用 UUID() 函数,能够生成时间、空间上都独一无二的值。听说只要是使用了 UUID,都不可能看到两个重复的 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 位。markdown
咱们关闭 MySQL,而后启动。ide
/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)
能够看到跟以前的数据不一样,包括第五组数据。由于第五组的值跟机器相关,因此,同一台机器第五组值不变,不一样机器则变。
主机 | 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
在此不赘述,请参考:MySQL AB 复制
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 模式。
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)
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 模式下,复制的数据和主服务器相同,亦即主从一致。
在 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)
–EOF–
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)