Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
apache
Shardingsphere
提交
fd6f5355
Shardingsphere
项目概览
apache
/
Shardingsphere
通知
56
Star
3
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Shardingsphere
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
fd6f5355
编写于
5月 20, 2020
作者:
L
Lucas
提交者:
GitHub
5月 20, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
issue-5688: Update mysql datasource checker (#5705)
Co-authored-by:
N
Lucas
<
qiulu3@jd.com
>
上级
925b8de8
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
110 addition
and
83 deletion
+110
-83
shardingsphere-scaling/shardingsphere-scaling-bootstrap/src/test/java/org/apache/shardingsphere/scaling/fixture/FixtureH2DataSourceChecker.java
...ingsphere/scaling/fixture/FixtureH2DataSourceChecker.java
+4
-0
shardingsphere-scaling/shardingsphere-scaling-core/src/main/java/org/apache/shardingsphere/scaling/core/job/preparer/ShardingScalingJobPreparer.java
...scaling/core/job/preparer/ShardingScalingJobPreparer.java
+1
-0
shardingsphere-scaling/shardingsphere-scaling-core/src/main/java/org/apache/shardingsphere/scaling/core/job/preparer/checker/DataSourceChecker.java
.../scaling/core/job/preparer/checker/DataSourceChecker.java
+7
-0
shardingsphere-scaling/shardingsphere-scaling-core/src/test/java/org/apache/shardingsphere/scaling/core/job/preparer/checker/AbstractDataSourceCheckerTest.java
...e/job/preparer/checker/AbstractDataSourceCheckerTest.java
+5
-0
shardingsphere-scaling/shardingsphere-scaling-mysql/pom.xml
shardingsphere-scaling/shardingsphere-scaling-mysql/pom.xml
+5
-0
shardingsphere-scaling/shardingsphere-scaling-mysql/src/main/java/org/apache/shardingsphere/scaling/mysql/MySQLBinlogDumper.java
...pache/shardingsphere/scaling/mysql/MySQLBinlogDumper.java
+2
-11
shardingsphere-scaling/shardingsphere-scaling-mysql/src/main/java/org/apache/shardingsphere/scaling/mysql/MySQLDataSourceChecker.java
.../shardingsphere/scaling/mysql/MySQLDataSourceChecker.java
+50
-26
shardingsphere-scaling/shardingsphere-scaling-mysql/src/main/java/org/apache/shardingsphere/scaling/mysql/client/MySQLClient.java
...ache/shardingsphere/scaling/mysql/client/MySQLClient.java
+6
-1
shardingsphere-scaling/shardingsphere-scaling-mysql/src/test/java/org/apache/shardingsphere/scaling/mysql/MySQLDataSourceCheckerTest.java
...rdingsphere/scaling/mysql/MySQLDataSourceCheckerTest.java
+25
-45
shardingsphere-scaling/shardingsphere-scaling-postgresql/src/main/java/org/apache/shardingsphere/scaling/postgresql/PostgreSQLDataSourceChecker.java
...phere/scaling/postgresql/PostgreSQLDataSourceChecker.java
+5
-0
未找到文件。
shardingsphere-scaling/shardingsphere-scaling-bootstrap/src/test/java/org/apache/shardingsphere/scaling/fixture/FixtureH2DataSourceChecker.java
浏览文件 @
fd6f5355
...
...
@@ -31,4 +31,8 @@ public final class FixtureH2DataSourceChecker implements DataSourceChecker {
@Override
public
void
checkPrivilege
(
final
Collection
<?
extends
DataSource
>
dataSources
)
{
}
@Override
public
void
checkVariable
(
final
Collection
<?
extends
DataSource
>
dataSources
)
{
}
}
shardingsphere-scaling/shardingsphere-scaling-core/src/main/java/org/apache/shardingsphere/scaling/core/job/preparer/ShardingScalingJobPreparer.java
浏览文件 @
fd6f5355
...
...
@@ -70,6 +70,7 @@ public final class ShardingScalingJobPreparer {
DataSourceChecker
dataSourceChecker
=
DataSourceCheckerCheckerFactory
.
newInstanceDataSourceChecker
(
databaseType
);
dataSourceChecker
.
checkConnection
(
dataSourceManager
.
getCachedDataSources
().
values
());
dataSourceChecker
.
checkPrivilege
(
dataSourceManager
.
getSourceDatasources
().
values
());
dataSourceChecker
.
checkVariable
(
dataSourceManager
.
getSourceDatasources
().
values
());
}
private
void
splitInventoryDataTasks
(
final
ShardingScalingJob
shardingScalingJob
,
final
DataSourceManager
dataSourceManager
)
{
...
...
shardingsphere-scaling/shardingsphere-scaling-core/src/main/java/org/apache/shardingsphere/scaling/core/job/preparer/checker/DataSourceChecker.java
浏览文件 @
fd6f5355
...
...
@@ -38,4 +38,11 @@ public interface DataSourceChecker {
* @param dataSources datasource connections
*/
void
checkPrivilege
(
Collection
<?
extends
DataSource
>
dataSources
);
/**
* Check datasource variables.
*
* @param dataSources datasource connections
*/
void
checkVariable
(
Collection
<?
extends
DataSource
>
dataSources
);
}
shardingsphere-scaling/shardingsphere-scaling-core/src/test/java/org/apache/shardingsphere/scaling/core/job/preparer/checker/AbstractDataSourceCheckerTest.java
浏览文件 @
fd6f5355
...
...
@@ -53,6 +53,11 @@ public final class AbstractDataSourceCheckerTest {
public
void
checkPrivilege
(
final
Collection
<?
extends
DataSource
>
dataSources
)
{
}
@Override
public
void
checkVariable
(
final
Collection
<?
extends
DataSource
>
dataSources
)
{
}
};
dataSources
=
new
ArrayList
<>();
dataSources
.
add
(
dataSource
);
...
...
shardingsphere-scaling/shardingsphere-scaling-mysql/pom.xml
浏览文件 @
fd6f5355
...
...
@@ -44,5 +44,10 @@
<groupId>
io.netty
</groupId>
<artifactId>
netty-all
</artifactId>
</dependency>
<dependency>
<groupId>
com.h2database
</groupId>
<artifactId>
h2
</artifactId>
<scope>
test
</scope>
</dependency>
</dependencies>
</project>
shardingsphere-scaling/shardingsphere-scaling-mysql/src/main/java/org/apache/shardingsphere/scaling/mysql/MySQLBinlogDumper.java
浏览文件 @
fd6f5355
...
...
@@ -88,22 +88,13 @@ public final class MySQLBinlogDumper extends AbstractShardingScalingExecutor imp
client
.
subscribe
(
binlogPosition
.
getFilename
(),
binlogPosition
.
getPosition
());
while
(
isRunning
())
{
AbstractBinlogEvent
event
=
client
.
poll
();
if
(
null
==
event
)
{
sleep
();
continue
;
if
(
null
!=
event
)
{
handleEvent
(
channel
,
uri
,
event
);
}
handleEvent
(
channel
,
uri
,
event
);
}
pushRecord
(
channel
,
new
FinishedRecord
(
new
NopLogPosition
()));
}
private
void
sleep
()
{
try
{
Thread
.
sleep
(
100
);
}
catch
(
InterruptedException
ignored
)
{
}
}
private
void
handleEvent
(
final
Channel
channel
,
final
JdbcUri
uri
,
final
AbstractBinlogEvent
event
)
{
if
(
event
instanceof
WriteRowsEvent
)
{
handleWriteRowsEvent
(
channel
,
uri
,
(
WriteRowsEvent
)
event
);
...
...
shardingsphere-scaling/shardingsphere-scaling-mysql/src/main/java/org/apache/shardingsphere/scaling/mysql/MySQLDataSourceChecker.java
浏览文件 @
fd6f5355
...
...
@@ -25,59 +25,83 @@ import java.sql.Connection;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* Data source checker for MySQL.
*/
public
final
class
MySQLDataSourceChecker
extends
AbstractDataSourceChecker
{
private
static
final
String
QUERY_SQL
=
"SELECT * FROM %s LIMIT 1
"
;
private
static
final
String
SHOW_GRANTS_SQL
=
"SHOW GRANTS
"
;
private
static
final
String
SHOW_MASTER_STATUS_SQL
=
"SHOW MASTER STATUS"
;
private
static
final
String
[][]
REQUIRED_PRIVILEGES
=
{{
"ALL PRIVILEGES"
,
"ON *.*"
},
{
"SELECT"
,
"REPLICATION SLAVE"
,
"REPLICATION CLIENT"
,
"ON *.*"
}};
private
static
final
String
SHOW_VARIABLES_SQL
=
"SHOW VARIABLES LIKE '%s'"
;
private
static
final
Map
<
String
,
String
>
REQUIRED_VARIABLES
=
new
HashMap
(
2
);
static
{
REQUIRED_VARIABLES
.
put
(
"LOG_BIN"
,
"ON"
);
REQUIRED_VARIABLES
.
put
(
"BINLOG_FORMAT"
,
"ROW"
);
}
@Override
public
void
checkPrivilege
(
final
Collection
<?
extends
DataSource
>
dataSources
)
{
for
(
DataSource
each
:
dataSources
)
{
checkPrivilege
0
(
each
);
checkPrivilege
(
each
);
}
}
private
void
checkPrivilege0
(
final
DataSource
dataSource
)
{
try
(
Connection
connection
=
dataSource
.
getConnection
())
{
String
tableName
=
getFirstTableName
(
connection
);
checkQueuePrivilege
(
connection
,
tableName
);
checkBinlogPrivilege
(
connection
);
private
void
checkPrivilege
(
final
DataSource
dataSource
)
{
try
(
Connection
connection
=
dataSource
.
getConnection
();
PreparedStatement
preparedStatement
=
connection
.
prepareStatement
(
SHOW_GRANTS_SQL
);
ResultSet
resultSet
=
preparedStatement
.
executeQuery
())
{
while
(
resultSet
.
next
())
{
String
privilege
=
resultSet
.
getString
(
1
).
toUpperCase
();
if
(
matchPrivileges
(
privilege
))
{
return
;
}
}
}
catch
(
SQLException
e
)
{
throw
new
PrepareFailedException
(
"
Datasources privileges check failed!
"
);
throw
new
PrepareFailedException
(
"
Source datasource check privileges failed.
"
);
}
throw
new
PrepareFailedException
(
"Source datasource is lack of SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* privileges."
);
}
private
String
getFirstTableName
(
final
Connection
connection
)
throws
SQLException
{
try
(
ResultSet
tables
=
connection
.
getMetaData
().
getTables
(
connection
.
getCatalog
(),
null
,
"%"
,
new
String
[]{
"TABLE"
}))
{
if
(
tables
.
next
())
{
return
tables
.
getString
(
3
);
}
throw
new
PrepareFailedException
(
"No tables find in the source datasource."
);
private
boolean
matchPrivileges
(
final
String
privilege
)
{
return
Arrays
.
stream
(
REQUIRED_PRIVILEGES
)
.
anyMatch
(
requiredPrivileges
->
Arrays
.
stream
(
requiredPrivileges
).
allMatch
(
required
->
privilege
.
contains
(
required
)));
}
@Override
public
void
checkVariable
(
final
Collection
<?
extends
DataSource
>
dataSources
)
{
for
(
DataSource
each
:
dataSources
)
{
checkVariable
(
each
);
}
}
private
void
checkQueuePrivilege
(
final
Connection
connection
,
final
String
tableName
)
{
try
(
PreparedStatement
preparedStatement
=
connection
.
prepareStatement
(
String
.
format
(
QUERY_SQL
,
tableName
)))
{
preparedStatement
.
executeQuery
();
private
void
checkVariable
(
final
DataSource
dataSource
)
{
try
(
Connection
connection
=
dataSource
.
getConnection
())
{
for
(
Map
.
Entry
<
String
,
String
>
entry
:
REQUIRED_VARIABLES
.
entrySet
())
{
checkVariable
(
connection
,
entry
);
}
}
catch
(
SQLException
e
)
{
throw
new
PrepareFailedException
(
"Source datasource
is lack of query privileges
."
);
throw
new
PrepareFailedException
(
"Source datasource
check variables failed
."
);
}
}
private
void
checkBinlogPrivilege
(
final
Connection
connection
)
{
try
(
PreparedStatement
preparedStatement
=
connection
.
prepareStatement
(
SHOW_MASTER_STATUS_SQL
);
ResultSet
resultSet
=
preparedStatement
.
executeQuery
())
{
if
(!
resultSet
.
next
())
{
throw
new
PrepareFailedException
(
"Source datasource do not open binlog."
);
private
void
checkVariable
(
final
Connection
connection
,
final
Map
.
Entry
<
String
,
String
>
entry
)
throws
SQLException
{
try
(
PreparedStatement
preparedStatement
=
connection
.
prepareStatement
(
String
.
format
(
SHOW_VARIABLES_SQL
,
entry
.
getKey
()));
ResultSet
resultSet
=
preparedStatement
.
executeQuery
())
{
resultSet
.
next
();
String
value
=
resultSet
.
getString
(
2
);
if
(!
entry
.
getValue
().
equalsIgnoreCase
(
value
))
{
throw
new
PrepareFailedException
(
String
.
format
(
"Source datasource required %s = %s, now is %s"
,
entry
.
getKey
(),
entry
.
getValue
(),
value
));
}
}
catch
(
SQLException
e
)
{
throw
new
PrepareFailedException
(
"Source datasource is lack of replication(binlog) privileges."
);
}
}
}
shardingsphere-scaling/shardingsphere-scaling-mysql/src/main/java/org/apache/shardingsphere/scaling/mysql/client/MySQLClient.java
浏览文件 @
fd6f5355
...
...
@@ -47,6 +47,7 @@ import lombok.extern.slf4j.Slf4j;
import
java.net.InetSocketAddress
;
import
java.util.concurrent.ArrayBlockingQueue
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.TimeUnit
;
/**
* MySQL Connector.
...
...
@@ -193,7 +194,11 @@ public final class MySQLClient {
* @return binlog event
*/
public
synchronized
AbstractBinlogEvent
poll
()
{
return
blockingEventQueue
.
poll
();
try
{
return
blockingEventQueue
.
poll
(
100
,
TimeUnit
.
MILLISECONDS
);
}
catch
(
InterruptedException
ignored
)
{
return
null
;
}
}
@SuppressWarnings
(
"unchecked"
)
...
...
shardingsphere-scaling/shardingsphere-scaling-mysql/src/test/java/org/apache/shardingsphere/scaling/mysql/MySQLDataSourceCheckerTest.java
浏览文件 @
fd6f5355
...
...
@@ -17,7 +17,6 @@
package
org.apache.shardingsphere.scaling.mysql
;
import
lombok.SneakyThrows
;
import
org.apache.shardingsphere.scaling.core.exception.PrepareFailedException
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -28,7 +27,6 @@ import org.mockito.junit.MockitoJUnitRunner;
import
javax.sql.DataSource
;
import
java.sql.Connection
;
import
java.sql.DatabaseMetaData
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
...
...
@@ -37,6 +35,7 @@ import java.util.Collection;
import
static
org
.
hamcrest
.
CoreMatchers
.
is
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyString
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
...
...
@@ -44,8 +43,6 @@ import static org.mockito.Mockito.when;
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
MySQLDataSourceCheckerTest
{
private
static
final
String
CATALOG
=
"test"
;
@Mock
private
Connection
connection
;
...
...
@@ -62,74 +59,57 @@ public class MySQLDataSourceCheckerTest {
@Before
public
void
setUp
()
throws
SQLException
{
DataSource
dataSource
=
mock
(
DataSource
.
class
);
mockConnection
();
mockResultSet
();
when
(
dataSource
.
getConnection
()).
thenReturn
(
connection
);
dataSources
=
new
ArrayList
<>();
dataSources
.
add
(
dataSource
);
dataSourceChecker
=
new
MySQLDataSourceChecker
();
when
(
connection
.
prepareStatement
(
anyString
())).
thenReturn
(
preparedStatement
);
when
(
preparedStatement
.
executeQuery
()).
thenReturn
(
resultSet
);
}
@SneakyThrows
private
void
mockConnection
()
{
DatabaseMetaData
metaData
=
mock
(
DatabaseMetaData
.
class
);
when
(
connection
.
getMetaData
()).
thenReturn
(
metaData
);
when
(
metaData
.
getTables
(
CATALOG
,
null
,
"%"
,
new
String
[]{
"TABLE"
})).
thenReturn
(
resultSet
);
when
(
connection
.
getCatalog
()).
thenReturn
(
CATALOG
);
when
(
connection
.
prepareStatement
(
"SELECT * FROM test LIMIT 1"
)).
thenReturn
(
preparedStatement
);
when
(
connection
.
prepareStatement
(
"SHOW MASTER STATUS"
)).
thenReturn
(
preparedStatement
);
}
@SneakyThrows
private
void
mockResultSet
()
{
@Test
public
void
assertCheckPrivilegeWithParticularSuccess
()
throws
SQLException
{
when
(
resultSet
.
next
()).
thenReturn
(
true
);
when
(
resultSet
.
getString
(
3
)).
thenReturn
(
"test"
);
when
(
resultSet
.
getString
(
1
)).
thenReturn
(
"GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO '%'@'%'"
);
dataSourceChecker
.
checkPrivilege
(
dataSources
);
verify
(
preparedStatement
,
Mockito
.
times
(
1
)).
executeQuery
();
}
@Test
public
void
assertCheckPrivilegeSuccess
()
throws
SQLException
{
public
void
assertCheckPrivilegeWithAllSuccess
()
throws
SQLException
{
when
(
resultSet
.
next
()).
thenReturn
(
true
);
when
(
resultSet
.
getString
(
1
)).
thenReturn
(
"GRANT ALL PRIVILEGES CLIENT ON *.* TO '%'@'%'"
);
dataSourceChecker
.
checkPrivilege
(
dataSources
);
verify
(
preparedStatement
,
Mockito
.
times
(
2
)).
executeQuery
();
verify
(
preparedStatement
,
Mockito
.
times
(
1
)).
executeQuery
();
}
@Test
public
void
assertCheckPrivilege
WithGettingTable
Failure
()
throws
SQLException
{
public
void
assertCheckPrivilegeFailure
()
throws
SQLException
{
when
(
resultSet
.
next
()).
thenReturn
(
false
);
try
{
dataSourceChecker
.
checkPrivilege
(
dataSources
);
}
catch
(
PrepareFailedException
checkFailedEx
)
{
assertThat
(
checkFailedEx
.
getMessage
(),
is
(
"
No tables find in the source datasource
."
));
assertThat
(
checkFailedEx
.
getMessage
(),
is
(
"
Source datasource is lack of SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* privileges
."
));
}
}
@Test
public
void
assertCheckPrivilegeWithNoQueryPrivilegeFailure
()
throws
SQLException
{
when
(
preparedStatement
.
executeQuery
()).
thenThrow
(
new
SQLException
());
try
{
dataSourceChecker
.
checkPrivilege
(
dataSources
);
}
catch
(
PrepareFailedException
checkFailedEx
)
{
assertThat
(
checkFailedEx
.
getMessage
(),
is
(
"Source datasource is lack of query privileges."
));
}
public
void
assertCheckVariableSuccess
()
throws
SQLException
{
when
(
resultSet
.
next
()).
thenReturn
(
true
,
true
);
when
(
resultSet
.
getString
(
2
)).
thenReturn
(
"ON"
,
"ROW"
);
dataSourceChecker
.
checkVariable
(
dataSources
);
verify
(
preparedStatement
,
Mockito
.
times
(
2
)).
executeQuery
();
}
@Test
public
void
assertCheckPrivilegeWithNoReplicationPrivilegeFailure
()
throws
SQLException
{
when
(
connection
.
prepareStatement
(
"SHOW MASTER STATUS"
)).
thenThrow
(
new
SQLException
());
public
void
assertCheckVariableFailure
()
throws
SQLException
{
when
(
resultSet
.
next
()).
thenReturn
(
true
,
true
);
when
(
resultSet
.
getString
(
2
)).
thenReturn
(
"OFF"
,
"ROW"
);
try
{
dataSourceChecker
.
check
Privileg
e
(
dataSources
);
dataSourceChecker
.
check
Variabl
e
(
dataSources
);
}
catch
(
PrepareFailedException
checkFailedEx
)
{
assertThat
(
checkFailedEx
.
getMessage
(),
is
(
"Source datasource
is lack of replication(binlog) privileges.
"
));
assertThat
(
checkFailedEx
.
getMessage
(),
is
(
"Source datasource
required LOG_BIN = ON, now is OFF
"
));
}
}
@Test
public
void
assertCheckPrivilegeWithNoBinlogFailure
()
throws
SQLException
{
when
(
resultSet
.
next
()).
thenReturn
(
true
,
false
);
try
{
dataSourceChecker
.
checkPrivilege
(
dataSources
);
}
catch
(
PrepareFailedException
checkFailedEx
)
{
assertThat
(
checkFailedEx
.
getMessage
(),
is
(
"Source datasource do not open binlog."
));
}
}
}
shardingsphere-scaling/shardingsphere-scaling-postgresql/src/main/java/org/apache/shardingsphere/scaling/postgresql/PostgreSQLDataSourceChecker.java
浏览文件 @
fd6f5355
...
...
@@ -50,4 +50,9 @@ public final class PostgreSQLDataSourceChecker extends AbstractDataSourceChecker
throw
new
PrepareFailedException
(
"Datasources check failed!"
);
}
}
@Override
public
void
checkVariable
(
final
Collection
<?
extends
DataSource
>
dataSources
)
{
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录