alibaba / druid

阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池
https://github.com/alibaba/druid/wiki
Apache License 2.0
27.9k stars 8.57k forks source link

WallFilter并发下失效 #3234

Open Burt-L opened 5 years ago

Burt-L commented 5 years ago

版本:druid-spring-boot-starter:1.1.16 场景:springboot:2.0.3 + mybatis-plus-boot-starter:2.3 + mysql 简单单表查询 SELECT user_id AS userId,user_name AS userName,mobile,create_by AS createBy,created_time AS createdTime,updated_by AS updatedBy,updated_time AS updatedTime,is_deleted AS isDeleted FROM test_user WHERE is_deleted=0 使用jmeter并发请求(Ramp-Up Period时间为0),会出现未在以上sql拼接limit的情况。且该sql后续执行都不会被WallFilter加上limit。

Burt-L commented 5 years ago

配置如下: spring.datasource.url=jdbc:mysql://xxx:3306/xxx?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true spring.datasource.username=xxx spring.datasource.password=xxx spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.initialSize=5 spring.datasource.druid.minIdle=5 spring.datasource.druid.maxActive=20 spring.datasource.druid.maxWait=60000 spring.datasource.druid.timeBetweenEvictionRunsMillis=60000 spring.datasource.druid.minEvictableIdleTimeMillis=300000 spring.datasource.druid.validationQuery=SELECT "x" spring.datasource.druid.testWhileIdle=true spring.datasource.druid.testOnBorrow=false spring.datasource.druid.testOnReturn=false spring.datasource.druid.poolPreparedStatements=true spring.datasource.druid.maxPoolPreparedStatementPerConnectionSize=20 spring.datasource.druid.filters=stat,wall,config spring.datasource.druid.filter.wall.enabled=true spring.datasource.druid.filter.wall.config.select-limit=3 spring.datasource.druid.filter.wall.db-type=mysql spring.datasource.druid.filter.wall.config.multi-statement-allow=true spring.datasource.druid.filter.stat.enabled=true spring.datasource.druid.filter.stat.merge-sql=false spring.datasource.druid.filter.stat.slow-sql-millis=5000

Burt-L commented 5 years ago

demo地址:https://gitee.com/lw_burt/burt-druid-feedback/tree/master

Burt-L commented 5 years ago

image image

Burt-L commented 5 years ago

image com.alibaba.druid.wall.WallProvider#checkInternal

Burt-L commented 5 years ago

image

请问com.alibaba.druid.wall.WallProvider#addWhiteSql 用!=比较这两个字符串是有啥深意

ksewen commented 5 years ago

@wenshao 初步定位可能的原因在于: 1、com.alibaba.druid.pool.DruidConnectionHolder#getStatementPool()可以看出PreparedStatementPool实例是跟着数据库连接的, LRUCache同理; 2、com.alibaba.druid.wall.WallFilter#init可以看出com.alibaba.druid.wall.spi.MySqlWallProvider实例是在数据源初始化的时候加载的,全局只有一个,whiteList和blackList同理; 3、当1条sql提交执行以后,无论成功失败,全局的whiteList和blackList里就会有这条sql的相关缓存,而这条sql在PreparedStatementPool的LRUCache里是不存在的,导致后续流程错误; 4、如果把连接池最大连接数设置为1,则不会出现 @Burt-L 描述的问题; 5、这应该是一个bug。