文/溫國兵
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許可證)