链接:https://my.oschina.net/actiontechoss/blog/10149077
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 17:57:59",
"roPort": "6447",
"roXPort": "6449",
"rwPort": "6446",
"rwSplitPort": "6450",
"rwXPort": "6448",
"version": "8.2.0"
}
}
}
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()
我们可以测试一下:
$ python test_router.py
PRIMARY - 3310
很好,我们可以使用读 / 写分离端口(6540)连接到集群并执行查询……。哦 ?!但为什么我们会直达主实例呢?我们不应该是去访问只读实例(副本实例)之一吗?
cnx.autocommit = True
然后我们可以再次运行该程序:
$ python test_router.py
SECONDARY - 3320
$ python test_router.py
SECONDARY - 3330
太棒了,达到预期效果工作!
cursor.add_attribute("router.access_mode", "read_write")
让我们再执行一次:
$ python test_router.py
PRIMARY - 3310
router.access_mode
可接受的值为:
auto
read_only
read_write
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()
让我们执行它:
$ python test_router2.py
1 : 3310, PRIMARY, 2023-11-09 17:44:00 : read from 3330
2 : 3310, PRIMARY, 2023-11-09 17:44:00 : read from 3330
3 : 3310, PRIMARY, 2023-11-09 17:44:00 : read from 3330
1 : 3310, PRIMARY, 2023-11-09 18:44:00 : read from 3320
2 : 3310, PRIMARY, 2023-11-09 18:44:00 : read from 3320
3 : 3310, PRIMARY, 2023-11-09 18:44:00 : read from 3320
1 : 3310, PRIMARY, 2023-11-09 17:44:00 : read from 3330
2 : 3310, PRIMARY, 2023-11-09 17:44:00 : read from 3330
3 : 3310, PRIMARY, 2023-11-09 17:44:00 : read from 3330
我们可以看到没有错误,并且我们写入了主节点并从所有辅助节点读取。请小心,如果在写入之前将 router.access_mode
的查询属性设置为 read_only
(第 16 行),您将收到错误,因为副本节点上不允许写入:
_mysql_connector.MySQLInterfaceError: The MySQL server is running with the --super-read-only option so it cannot execute this statement
自动提交中的读操作
事务中的读操作(默认情况下,这是读 / 写事务)
只读事务中的读操作
具有多次插入和回滚的事务
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()
让我们执行脚本:
$ python test_router3.py
SECONDARY - 3320
PRIMARY - 3310
SECONDARY - 3320
我们可以看到,第一个操作到达了副本实例,第二个操作(即事务)到达了主节点。只读事务到达副本节点。对于作为我们回滚事务一部分的多次写入,我们没有收到任何错误。
往期推荐
点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦