mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
fixed schema blackFilter & mysql 8.4
This commit is contained in:
@@ -30,18 +30,17 @@ import com.alibaba.otter.canal.parse.driver.mysql.utils.PacketManager;
|
|||||||
*/
|
*/
|
||||||
public class MysqlConnector {
|
public class MysqlConnector {
|
||||||
|
|
||||||
|
public static final int timeout = 5 * 1000; // 5s
|
||||||
private static final Logger logger = LoggerFactory.getLogger(MysqlConnector.class);
|
private static final Logger logger = LoggerFactory.getLogger(MysqlConnector.class);
|
||||||
private InetSocketAddress address;
|
private InetSocketAddress address;
|
||||||
private String username;
|
private String username;
|
||||||
private String password;
|
private String password;
|
||||||
private SslInfo sslInfo;
|
private SslInfo sslInfo;
|
||||||
|
|
||||||
private String defaultSchema;
|
private String defaultSchema;
|
||||||
private int soTimeout = 30 * 1000;
|
private int soTimeout = 30 * 1000;
|
||||||
private int connTimeout = 5 * 1000;
|
private int connTimeout = 5 * 1000;
|
||||||
private int receiveBufferSize = 16 * 1024;
|
private int receiveBufferSize = 16 * 1024;
|
||||||
private int sendBufferSize = 16 * 1024;
|
private int sendBufferSize = 16 * 1024;
|
||||||
|
|
||||||
private SocketChannel channel;
|
private SocketChannel channel;
|
||||||
private volatile boolean dumping = false;
|
private volatile boolean dumping = false;
|
||||||
// mysql connectionId
|
// mysql connectionId
|
||||||
@@ -50,8 +49,6 @@ public class MysqlConnector {
|
|||||||
// serverVersion
|
// serverVersion
|
||||||
private String serverVersion;
|
private String serverVersion;
|
||||||
|
|
||||||
public static final int timeout = 5 * 1000; // 5s
|
|
||||||
|
|
||||||
public MysqlConnector(){
|
public MysqlConnector(){
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,16 +197,13 @@ public class MysqlConnector {
|
|||||||
}
|
}
|
||||||
HandshakeInitializationPacket handshakePacket = new HandshakeInitializationPacket();
|
HandshakeInitializationPacket handshakePacket = new HandshakeInitializationPacket();
|
||||||
handshakePacket.fromBytes(body);
|
handshakePacket.fromBytes(body);
|
||||||
byte serverCharsetNumber
|
byte serverCharsetNumber = (handshakePacket.serverCharsetNumber != 0) ? handshakePacket.serverCharsetNumber : 33;
|
||||||
= (handshakePacket.serverCharsetNumber != 0)
|
|
||||||
? handshakePacket.serverCharsetNumber
|
|
||||||
: 33;
|
|
||||||
SslMode sslMode = sslInfo != null ? sslInfo.getSslMode() : SslMode.DISABLED;
|
SslMode sslMode = sslInfo != null ? sslInfo.getSslMode() : SslMode.DISABLED;
|
||||||
if (sslMode != SslMode.DISABLED) {
|
if (sslMode != SslMode.DISABLED) {
|
||||||
boolean serverSupportSsl = (handshakePacket.serverCapabilities & CLIENT_SSL) > 0;
|
boolean serverSupportSsl = (handshakePacket.serverCapabilities & CLIENT_SSL) > 0;
|
||||||
if (!serverSupportSsl) {
|
if (!serverSupportSsl) {
|
||||||
throw new IOException("MySQL Server does not support SSL: " + address
|
throw new IOException("MySQL Server does not support SSL: " + address + " serverCapabilities: "
|
||||||
+ " serverCapabilities: " + handshakePacket.serverCapabilities);
|
+ handshakePacket.serverCapabilities);
|
||||||
}
|
}
|
||||||
byte[] sslPacket = new SslRequestCommandPacket(serverCharsetNumber).toBytes();
|
byte[] sslPacket = new SslRequestCommandPacket(serverCharsetNumber).toBytes();
|
||||||
HeaderPacket sslHeader = new HeaderPacket();
|
HeaderPacket sslHeader = new HeaderPacket();
|
||||||
@@ -230,10 +224,9 @@ public class MysqlConnector {
|
|||||||
serverVersion = handshakePacket.serverVersion; // 记录serverVersion
|
serverVersion = handshakePacket.serverVersion; // 记录serverVersion
|
||||||
logger.info("handshake initialization packet received, prepare the client authentication packet to send");
|
logger.info("handshake initialization packet received, prepare the client authentication packet to send");
|
||||||
// 某些老协议的 server 默认不返回 auth plugin,需要使用默认的 mysql_native_password
|
// 某些老协议的 server 默认不返回 auth plugin,需要使用默认的 mysql_native_password
|
||||||
String authPluginName
|
String authPluginName = (handshakePacket.authPluginName != null
|
||||||
= (handshakePacket.authPluginName != null && handshakePacket.authPluginName.length > 0)
|
&& handshakePacket.authPluginName.length > 0) ? new String(
|
||||||
? new String(handshakePacket.authPluginName)
|
handshakePacket.authPluginName) : "mysql_native_password";
|
||||||
: "mysql_native_password";
|
|
||||||
logger.info("auth plugin: {}", authPluginName);
|
logger.info("auth plugin: {}", authPluginName);
|
||||||
boolean isSha2Password = false;
|
boolean isSha2Password = false;
|
||||||
ClientAuthenticationPacket clientAuth;
|
ClientAuthenticationPacket clientAuth;
|
||||||
@@ -490,10 +483,6 @@ public class MysqlConnector {
|
|||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getConnectionId() {
|
public long getConnectionId() {
|
||||||
return connectionId;
|
return connectionId;
|
||||||
}
|
}
|
||||||
@@ -522,6 +511,10 @@ public class MysqlConnector {
|
|||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
public String getServerVersion() {
|
public String getServerVersion() {
|
||||||
return serverVersion;
|
return serverVersion;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -603,6 +603,32 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MySQL 8.4版本开始部分命令出现变化
|
||||||
|
* https://dev.mysql.com/doc/relnotes/mysql/8.4/en/news-8-4-0.html#mysqld-8-4-0-deprecation-removal
|
||||||
|
*
|
||||||
|
* @param major
|
||||||
|
* @param minor
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean atLeast(int major, int minor) {
|
||||||
|
if (isMariaDB()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String version = connector.getServerVersion();
|
||||||
|
if (StringUtils.isNotEmpty(version)) {
|
||||||
|
String[] parts = version.split("\\.");
|
||||||
|
int majorVer = Integer.parseInt(parts[0]);
|
||||||
|
int minorVer = Integer.parseInt(parts[1]);
|
||||||
|
return (majorVer > major) || (majorVer == major && minorVer >= minor);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean atLeastMySQL84() {
|
||||||
|
return atLeast(8, 4);
|
||||||
|
}
|
||||||
|
|
||||||
private void accumulateReceivedBytes(long x) {
|
private void accumulateReceivedBytes(long x) {
|
||||||
if (receivedBinlogBytes != null) {
|
if (receivedBinlogBytes != null) {
|
||||||
receivedBinlogBytes.addAndGet(x);
|
receivedBinlogBytes.addAndGet(x);
|
||||||
@@ -756,23 +782,4 @@ public class MysqlConnection implements ErosaConnection {
|
|||||||
return connector.getServerVersion() != null && connector.getServerVersion().toLowerCase().contains("mariadb");
|
return connector.getServerVersion() != null && connector.getServerVersion().toLowerCase().contains("mariadb");
|
||||||
}
|
}
|
||||||
|
|
||||||
// MySQL 8.4版本开始部分命令出现变化
|
|
||||||
// https://dev.mysql.com/doc/relnotes/mysql/8.4/en/news-8-4-0.html#mysqld-8-4-0-deprecation-removal
|
|
||||||
public boolean atLeast(int major, int minor) {
|
|
||||||
if (isMariaDB()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String version = connector.getServerVersion();
|
|
||||||
if (StringUtils.isNotEmpty(version)) {
|
|
||||||
String[] parts = version.split("\\.");
|
|
||||||
int majorVer = Integer.parseInt(parts[0]);
|
|
||||||
int minorVer = Integer.parseInt(parts[1]);
|
|
||||||
return (majorVer > major) || (majorVer == major && minorVer >= minor);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean atLeastMySQL84() {
|
|
||||||
return atLeast(8, 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -668,20 +668,20 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
* 查询当前的binlog位置
|
* 查询当前的binlog位置
|
||||||
*/
|
*/
|
||||||
private EntryPosition findEndPosition(MysqlConnection mysqlConnection) {
|
private EntryPosition findEndPosition(MysqlConnection mysqlConnection) {
|
||||||
String showSql = "SHOW MASTER STATUS";
|
String showSql = "show master status";
|
||||||
try {
|
try {
|
||||||
if (mysqlConnection.atLeastMySQL84()) {
|
if (mysqlConnection.atLeastMySQL84()) {
|
||||||
showSql = "SHOW BINARY LOG STATUS";
|
// 8.4新语法
|
||||||
}
|
showSql = "show binary log status";
|
||||||
if (multiStreamEnable) {
|
} else if (multiStreamEnable) {
|
||||||
|
// 兼容polardb-x的多流binlog
|
||||||
showSql = "show master status with " + destination;
|
showSql = "show master status with " + destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultSetPacket packet = mysqlConnection.query(showSql);
|
ResultSetPacket packet = mysqlConnection.query(showSql);
|
||||||
List<String> fields = packet.getFieldValues();
|
List<String> fields = packet.getFieldValues();
|
||||||
if (CollectionUtils.isEmpty(fields)) {
|
if (CollectionUtils.isEmpty(fields)) {
|
||||||
throw new CanalParseException(
|
throw new CanalParseException(
|
||||||
"command : '" + showSql +"' has an error! pls check. you need (at least one of) the SUPER,REPLICATION CLIENT privilege(s) for this operation");
|
"command : '" + showSql + "' has an error! pls check. you need (at least one of) the SUPER,REPLICATION CLIENT privilege(s) for this operation");
|
||||||
}
|
}
|
||||||
EntryPosition endPosition = new EntryPosition(fields.get(0), Long.valueOf(fields.get(1)));
|
EntryPosition endPosition = new EntryPosition(fields.get(0), Long.valueOf(fields.get(1)));
|
||||||
if (isGTIDMode() && fields.size() > 4) {
|
if (isGTIDMode() && fields.size() > 4) {
|
||||||
@@ -697,7 +697,7 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
}
|
}
|
||||||
return endPosition;
|
return endPosition;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CanalParseException("command : '" + showSql +"' has an error! ", e);
|
throw new CanalParseException("command : '" + showSql + "' has an error!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,7 +728,12 @@ public class MysqlEventParser extends AbstractMysqlEventParser implements CanalE
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private SlaveEntryPosition findSlavePosition(MysqlConnection mysqlConnection) {
|
private SlaveEntryPosition findSlavePosition(MysqlConnection mysqlConnection) {
|
||||||
try {
|
try {
|
||||||
ResultSetPacket packet = mysqlConnection.query("show slave status");
|
String showSql = "show slave stauts";
|
||||||
|
if (mysqlConnection.atLeastMySQL84()) {
|
||||||
|
// 兼容mysql 8.4
|
||||||
|
showSql = "show replica status";
|
||||||
|
}
|
||||||
|
ResultSetPacket packet = mysqlConnection.query(showSql);
|
||||||
List<FieldPacket> names = packet.getFieldDescriptors();
|
List<FieldPacket> names = packet.getFieldDescriptors();
|
||||||
List<String> fields = packet.getFieldValues();
|
List<String> fields = packet.getFieldValues();
|
||||||
if (CollectionUtils.isEmpty(fields)) {
|
if (CollectionUtils.isEmpty(fields)) {
|
||||||
|
|||||||
@@ -207,6 +207,11 @@ public class DatabaseTableMeta implements TableMetaTSDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (String schema : schemas) {
|
for (String schema : schemas) {
|
||||||
|
// 如果schema命中黑名单,直接跳过
|
||||||
|
// 解决部分数据库可以看到database,但实际表级别无权限的情况
|
||||||
|
if (blackFilter != null && blackFilter.filter(schema + ".%")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// filter views
|
// filter views
|
||||||
packet = connection.query("show full tables from `" + schema + "` where Table_type = 'BASE TABLE'");
|
packet = connection.query("show full tables from `" + schema + "` where Table_type = 'BASE TABLE'");
|
||||||
columnSize = packet.getFieldDescriptors().size();
|
columnSize = packet.getFieldDescriptors().size();
|
||||||
|
|||||||
Reference in New Issue
Block a user