作者:Frederic Descamps,MySQL 社區(qū)經(jīng)理
翻譯:愛可生開源社區(qū)
如您所知,MySQL 8.2 發(fā)布了最令人期待的功能之一:讀寫分離。
在這篇文章中,我們將了解如何將它與 MySQL-Connector/Python 一起使用。
架構(gòu)
為了使用我們的 Python 程序,我們將使用 InnoDB Cluster。
以下是在 MySQL Shell 中查詢 Cluster 的狀態(tài):
JS > cluster.status() { "clusterName": "fred", "defaultReplicaSet": { "name": "default", "primary": "127.0.0.1:3310", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "127.0.0.1:3310": { "address": "127.0.0.1:3310", "memberRole": "PRIMARY", "mode": "R/W", "readReplicas": {}, "replicationLag": "applier_queue_applied", "role": "HA", "status": "ONLINE", "version": "8.2.0" }, "127.0.0.1:3320": { "address": "127.0.0.1:3320", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": "applier_queue_applied", "role": "HA", "status": "ONLINE", "version": "8.2.0" }, "127.0.0.1:3330": { "address": "127.0.0.1:3330", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": "applier_queue_applied", "role": "HA", "status": "ONLINE", "version": "8.2.0" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "127.0.0.1:3310" } JS > cluster.listRouters() { "clusterName": "fred", "routers": { "dynabook::system": { "hostname": "dynabook", "lastCheckIn": "2023-11-09 1759", "roPort": "6447", "roXPort": "6449", "rwPort": "6446", "rwSplitPort": "6450", "rwXPort": "6448", "version": "8.2.0" } } }
MySQL Connector/Python
Python 程序使用 MySQL-Connector/Python 8.2.0。
初始化測(cè)試腳本代碼:
import mysql.connector cnx = mysql.connector.connect(user='python', passowrd='Passw0rd!Python', host='127.0.0.1', port='6450') cursor = cnx.cursor() query = ("""select member_role, @@port port from performance_schema.replication_group_members where member_id=@@server_uuid""") for (role, port) in cursor: print("{} - {}".format(role, port)) cursor.close() cnx.close()
我們可以測(cè)試一下:
$ python test_router.py PRIMARY - 3310
很好,我們可以使用讀 / 寫分離端口(6540)連接到集群并執(zhí)行查詢……。哦 ?!但為什么我們會(huì)直達(dá)主實(shí)例呢?
我們不應(yīng)該是去訪問只讀實(shí)例(副本實(shí)例)之一嗎?
autocommit
Connector/Python 默認(rèn)禁用自動(dòng)提交(請(qǐng)參閱 MySQLConnection.autocommit 屬性)。并且讀寫分離功能必須啟用自動(dòng)提交才能正常工作。
在第 8 行上方添加以下代碼:
cnx.autocommit = True
然后我們可以再次運(yùn)行該程序:
$ python test_router.py SECONDARY - 3320 $ python test_router.py SECONDARY - 3330
太棒了,達(dá)到預(yù)期效果工作!
查詢屬性
現(xiàn)在讓我們看看如何在主節(jié)點(diǎn)上強(qiáng)制執(zhí)行查詢。
MySQL Router 提供了使用查詢屬性來(lái)強(qiáng)制執(zhí)行讀 / 寫拆分決策的可能性:router.access_mode。
在執(zhí)行查詢 (cursor.execute (query) ) 之前添加以下行:
cursor.add_attribute("router.access_mode", "read_write")
讓我們?cè)賵?zhí)行一次:
$ python test_router.py PRIMARY - 3310router.access_mode可接受的值為:
auto
read_only
read_write
測(cè)試 DML 語(yǔ)句
讓我們嘗試一些不同的東西,我們將向表中插入行。
我們將使用下表:
CREATE TABLE `t1` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `port` int DEFAULT NULL, `role` varchar(15) DEFAULT NULL, `timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB ;
我們將使用以下 Python 腳本:
import mysql.connector cnx = mysql.connector.connect(user='python', password='Passw0rd!Python', host='127.0.0.1', port='6450', database='test') cnx.autocommit = True cursor = cnx.cursor() for i in range(3): query = ("""insert into t1 values(0, @@port, ( select member_role from performance_schema.replication_group_members where member_id=@@server_uuid), now())""") cursor.execute(query) cursor.close() cnx.close() for i in range(3): cnx = mysql.connector.connect(user='python', password='Passw0rd!Python', host='127.0.0.1', port='6450', database='test') cnx.autocommit = True cursor = cnx.cursor() query = ("""select *, @@port port_read from t1""") cursor.execute(query) for (id, port, role, timestamp, port_read) in cursor: print("{} : {}, {}, {} : read from {}".format(id, port, role, timestamp, port_read)) cursor.close() cnx.close()
讓我們執(zhí)行它:
$ python test_router2.py 1 : 3310, PRIMARY, 2023-11-09 1700 : read from 3330 2 : 3310, PRIMARY, 2023-11-09 1700 : read from 3330 3 : 3310, PRIMARY, 2023-11-09 1700 : read from 3330 1 : 3310, PRIMARY, 2023-11-09 1800 : read from 3320 2 : 3310, PRIMARY, 2023-11-09 1800 : read from 3320 3 : 3310, PRIMARY, 2023-11-09 1800 : read from 3320 1 : 3310, PRIMARY, 2023-11-09 1700 : read from 3330 2 : 3310, PRIMARY, 2023-11-09 1700 : read from 3330 3 : 3310, PRIMARY, 2023-11-09 1700 : read from 3330
我們可以看到?jīng)]有錯(cuò)誤,并且我們寫入了主節(jié)點(diǎn)并從所有輔助節(jié)點(diǎn)讀取。
請(qǐng)小心,如果在寫入之前將router.access_mode的查詢屬性設(shè)置為read_only(第 16 行),您將收到錯(cuò)誤,因?yàn)楦北竟?jié)點(diǎn)上不允許寫入:
_mysql_connector.MySQLInterfaceError: The MySQL server is running with the --super-read-only option so it cannot execute this statement
事務(wù)
現(xiàn)在我們要玩一下事務(wù)。我們創(chuàng)建一個(gè)新腳本來(lái)執(zhí)行多個(gè)事務(wù):
自動(dòng)提交中的讀操作
事務(wù)中的讀操作(默認(rèn)情況下,這是讀 / 寫事務(wù))
只讀事務(wù)中的讀操作
具有多次插入和回滾的事務(wù)
這是程序的源碼:
import mysql.connector cnx = mysql.connector.connect(user='python', password='Passw0rd!Python', host='127.0.0.1', port='6450', database='test') cnx.autocommit = True cursor = cnx.cursor() query = ("""select member_role, @@port port from performance_schema.replication_group_members where member_id=@@server_uuid""") cursor.execute(query) for (role, port) in cursor: print("{} - {}".format(role, port)) cnx.start_transaction() query = ("""select member_role, @@port port from performance_schema.replication_group_members where member_id=@@server_uuid""") cursor.execute(query) for (role, port) in cursor: print("{} - {}".format(role, port)) cnx.commit() cnx.start_transaction(readonly=True) query = ("""select member_role, @@port port from performance_schema.replication_group_members where member_id=@@server_uuid""") cursor.execute(query) for (role, port) in cursor: print("{} - {}".format(role, port)) cnx.commit() cnx.start_transaction() for i in range(3): query = ("""insert into t1 values(0, @@port, ( select member_role from performance_schema.replication_group_members where member_id=@@server_uuid), now())""") cursor.execute(query) cnx.rollback() cursor.close() cnx.close()
讓我們執(zhí)行腳本:
$ python test_router3.py SECONDARY - 3320 PRIMARY - 3310 SECONDARY - 3320
我們可以看到,第一個(gè)操作到達(dá)了副本實(shí)例,第二個(gè)操作(即事務(wù))到達(dá)了主節(jié)點(diǎn)。
只讀事務(wù)到達(dá)副本節(jié)點(diǎn)。
對(duì)于作為我們回滾事務(wù)一部分的多次寫入,我們沒有收到任何錯(cuò)誤。
結(jié)論
我們已經(jīng)看到將 MySQL Connector/Python 與 MySQL 8.2 讀寫分離一起用于 InnoDB Cluster 是多么容易。
享受通過 MySQL Connector / Python 使用 MySQL 讀寫分離!
審核編輯:湯梓紅
-
MySQL
+關(guān)注
關(guān)注
1文章
804瀏覽量
26528 -
C程序
+關(guān)注
關(guān)注
4文章
254瀏覽量
36027 -
python
+關(guān)注
關(guān)注
56文章
4792瀏覽量
84627
原文標(biāo)題:Python如何使用MySQL 8.2讀寫分離?
文章出處:【微信號(hào):OSC開源社區(qū),微信公眾號(hào):OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論