diff --git a/Makefile b/Makefile index 3fd5d6ebf..fb0c3b2c1 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ DEBUG=${ALL_DEBUG} #export DEBUG #export OPTZ #export EXTRALINK -CURVER=1.2.2 +CURVER=1.2.3 DISTRO := $(shell gawk -F= '/^NAME/{print $$2}' /etc/os-release) .PHONY: default @@ -48,7 +48,7 @@ clean: cd lib && ${MAKE} clean cd src && ${MAKE} clean -packages: centos6.7 centos7 centos6.7-dbg centos7-dbg ubuntu12 ubuntu14 debian7 debian8 ubuntu12-dbg ubuntu14-dbg debian7-dbg debian8-dbg +packages: centos6.7 centos7 centos6.7-dbg centos7-dbg ubuntu12 ubuntu14 debian7 debian8 ubuntu12-dbg ubuntu14-dbg debian7-dbg debian8-dbg ubuntu16 ubuntu16-dbg fedora24 fedora24-dbg .PHONY: packages @@ -64,14 +64,20 @@ centos6.7-dbg: binaries/proxysql-${CURVER}-1-dbg-centos67.x86_64.rpm centos7-dbg: binaries/proxysql-${CURVER}-1-dbg-centos7.x86_64.rpm .PHONY: centos7-dbg +fedora24: binaries/proxysql-${CURVER}-1-fedora24.x86_64.rpm +.PHONY: fedora24 + +fedora24-dbg: binaries/proxysql-${CURVER}-1-dbg-fedora24.x86_64.rpm +.PHONY: fedora24-dbg + ubuntu12: binaries/proxysql_${CURVER}-ubuntu12_amd64.deb .PHONY: ubuntu12 ubuntu14: binaries/proxysql_${CURVER}-ubuntu14_amd64.deb .PHONY: ubuntu14 -ubuntu15: binaries/proxysql_${CURVER}-ubuntu15_amd64.deb -.PHONY: ubuntu15 +ubuntu16: binaries/proxysql_${CURVER}-ubuntu16_amd64.deb +.PHONY: ubuntu16 debian7: binaries/proxysql_${CURVER}-debian7_amd64.deb .PHONY: debian7 @@ -85,8 +91,8 @@ ubuntu12-dbg: binaries/proxysql_${CURVER}-dbg-ubuntu12_amd64.deb ubuntu14-dbg: binaries/proxysql_${CURVER}-dbg-ubuntu14_amd64.deb .PHONY: ubuntu14-dbg -ubuntu15-dbg: binaries/proxysql_${CURVER}-dbg-ubuntu15_amd64.deb -.PHONY: ubuntu15-dbg +ubuntu16-dbg: binaries/proxysql_${CURVER}-dbg-ubuntu16_amd64.deb +.PHONY: ubuntu16-dbg debian7-dbg: binaries/proxysql_${CURVER}-dbg-debian7_amd64.deb .PHONY: debian7-dbg @@ -168,6 +174,43 @@ binaries/proxysql-${CURVER}-1-dbg-centos7.x86_64.rpm: docker rm centos7_build +binaries/proxysql-${CURVER}-1-fedora24.x86_64.rpm: + docker stop fedora24_build || true + docker rm fedora24_build || true + docker create --name fedora24_build renecannao/proxysql:build-fedora24 bash -c "while : ; do sleep 10 ; done" + docker start fedora24_build + docker exec fedora24_build bash -c "cd /opt; git clone -b v${CURVER} https://github.com/sysown/proxysql.git proxysql" + docker exec fedora24_build bash -c "cd /opt/proxysql; ${MAKE} clean && ${MAKE} -j 4 build_deps && ${MAKE}" + docker exec -it fedora24_build bash -c "cd /opt/proxysql ; mkdir -p proxysql/usr/bin; mkdir -p proxysql/etc; cp src/proxysql proxysql/usr/bin/; cp -a etc proxysql ; mkdir -p proxysql/usr/share/proxysql/tools ; cp -a tools/proxysql_galera_checker.sh tools/proxysql_galera_writer.pl proxysql/usr/share/proxysql/tools ; mv proxysql proxysql-${CURVER} ; tar czvf proxysql-${CURVER}.tar.gz proxysql-${CURVER}" + docker exec -it fedora24_build bash -c "mkdir -p /root/rpmbuild/{RPMS,SRPMS,BUILD,SOURCES,SPECS,tmp}" + docker cp docker/images/proxysql/fedora24-build/rpmmacros fedora24_build:/root/.rpmmacros + docker cp docker/images/proxysql/fedora24-build/proxysql.spec fedora24_build:/root/rpmbuild/SPECS/proxysql.spec + docker exec -it fedora24_build bash -c "cp /opt/proxysql/proxysql-${CURVER}.tar.gz /root/rpmbuild/SOURCES" + docker exec -it fedora24_build bash -c "cd /root/rpmbuild; rpmbuild -ba SPECS/proxysql.spec" + docker exec -it fedora24_build bash -c "cp /root/rpmbuild/RPMS/x86_64/proxysql-${CURVER}-1.x86_64.rpm /root/rpm" + docker cp fedora24_build:/root/rpmbuild/RPMS/x86_64/proxysql-${CURVER}-1.x86_64.rpm ./binaries/proxysql-${CURVER}-1-fedora24.x86_64.rpm + docker stop fedora24_build + docker rm fedora24_build + +binaries/proxysql-${CURVER}-1-dbg-fedora24.x86_64.rpm: + docker stop fedora24_build || true + docker rm fedora24_build || true + docker create --name fedora24_build renecannao/proxysql:build-fedora24 bash -c "while : ; do sleep 10 ; done" + docker start fedora24_build + docker exec fedora24_build bash -c "cd /opt; git clone -b v${CURVER} https://github.com/sysown/proxysql.git proxysql" + docker exec fedora24_build bash -c "cd /opt/proxysql; ${MAKE} clean && ${MAKE} -j 4 build_deps && ${MAKE} debug" + docker exec -it fedora24_build bash -c "cd /opt/proxysql ; mkdir -p proxysql/usr/bin; mkdir -p proxysql/etc; cp src/proxysql proxysql/usr/bin/; cp -a etc proxysql ; mkdir -p proxysql/usr/share/proxysql/tools ; cp -a tools/proxysql_galera_checker.sh tools/proxysql_galera_writer.pl proxysql/usr/share/proxysql/tools ; mv proxysql proxysql-${CURVER} ; tar czvf proxysql-${CURVER}.tar.gz proxysql-${CURVER}" + docker exec -it fedora24_build bash -c "mkdir -p /root/rpmbuild/{RPMS,SRPMS,BUILD,SOURCES,SPECS,tmp}" + docker cp docker/images/proxysql/fedora24-build/rpmmacros fedora24_build:/root/.rpmmacros + docker cp docker/images/proxysql/fedora24-build/proxysql.spec fedora24_build:/root/rpmbuild/SPECS/proxysql.spec + docker exec -it fedora24_build bash -c "cp /opt/proxysql/proxysql-${CURVER}.tar.gz /root/rpmbuild/SOURCES" + docker exec -it fedora24_build bash -c "cd /root/rpmbuild; rpmbuild -ba SPECS/proxysql.spec" + docker exec -it fedora24_build bash -c "cp /root/rpmbuild/RPMS/x86_64/proxysql-${CURVER}-1.x86_64.rpm /root/rpm" + docker cp fedora24_build:/root/rpmbuild/RPMS/x86_64/proxysql-${CURVER}-1.x86_64.rpm ./binaries/proxysql-${CURVER}-1-dbg-fedora24.x86_64.rpm + docker stop fedora24_build + docker rm fedora24_build + + binaries/proxysql_${CURVER}-ubuntu12_amd64.deb: docker stop ubuntu12_build || true docker rm ubuntu12_build || true @@ -194,18 +237,18 @@ binaries/proxysql_${CURVER}-ubuntu14_amd64.deb: docker stop ubuntu14_build docker rm ubuntu14_build -binaries/proxysql_${CURVER}-ubuntu15_amd64.deb: - docker stop ubuntu15_build || true - docker rm ubuntu15_build || true - docker create --name ubuntu15_build renecannao/proxysql:build-ubuntu15 bash -c "while : ; do sleep 10 ; done" - docker start ubuntu15_build - docker exec ubuntu15_build bash -c "cd /opt; git clone -b v${CURVER} https://github.com/sysown/proxysql.git proxysql" - docker exec ubuntu15_build bash -c "cd /opt/proxysql; ${MAKE} clean && ${MAKE} -j 4 build_deps && ${MAKE} -j 4" - docker cp docker/images/proxysql/ubuntu-15.10-build/proxysql.ctl ubuntu15_build:/opt/proxysql/ - docker exec ubuntu15_build bash -c "cd /opt/proxysql; cp src/proxysql . ; equivs-build proxysql.ctl" - docker cp ubuntu15_build:/opt/proxysql/proxysql_${CURVER}_amd64.deb ./binaries/proxysql_${CURVER}-ubuntu15_amd64.deb - docker stop ubuntu15_build - docker rm ubuntu15_build +binaries/proxysql_${CURVER}-ubuntu16_amd64.deb: + docker stop ubuntu16_build || true + docker rm ubuntu16_build || true + docker create --name ubuntu16_build renecannao/proxysql:build-ubuntu16 bash -c "while : ; do sleep 10 ; done" + docker start ubuntu16_build + docker exec ubuntu16_build bash -c "cd /opt; git clone -b v${CURVER} https://github.com/sysown/proxysql.git proxysql" + docker exec ubuntu16_build bash -c "cd /opt/proxysql; ${MAKE} clean && ${MAKE} -j 4 build_deps && ${MAKE} -j 4" + docker cp docker/images/proxysql/ubuntu-16.04-build/proxysql.ctl ubuntu16_build:/opt/proxysql/ + docker exec ubuntu16_build bash -c "cd /opt/proxysql; cp src/proxysql . ; equivs-build proxysql.ctl" + docker cp ubuntu16_build:/opt/proxysql/proxysql_${CURVER}_amd64.deb ./binaries/proxysql_${CURVER}-ubuntu16_amd64.deb + docker stop ubuntu16_build + docker rm ubuntu16_build binaries/proxysql_${CURVER}-debian7_amd64.deb: docker stop debian7_build || true @@ -260,18 +303,18 @@ binaries/proxysql_${CURVER}-dbg-ubuntu14_amd64.deb: docker stop ubuntu14_build docker rm ubuntu14_build -binaries/proxysql_${CURVER}-dbg-ubuntu15_amd64.deb: - docker stop ubuntu15_build || true - docker rm ubuntu15_build || true - docker create --name ubuntu15_build renecannao/proxysql:build-ubuntu15 bash -c "while : ; do sleep 10 ; done" - docker start ubuntu15_build - docker exec ubuntu15_build bash -c "cd /opt; git clone -b v${CURVER} https://github.com/sysown/proxysql.git proxysql" - docker exec ubuntu15_build bash -c "cd /opt/proxysql; ${MAKE} clean && ${MAKE} -j 4 build_deps && ${MAKE} debug" - docker cp docker/images/proxysql/ubuntu-15.10-build/proxysql.ctl ubuntu15_build:/opt/proxysql/ - docker exec ubuntu15_build bash -c "cd /opt/proxysql; cp src/proxysql . ; equivs-build proxysql.ctl" - docker cp ubuntu15_build:/opt/proxysql/proxysql_${CURVER}_amd64.deb ./binaries/proxysql_${CURVER}-ubuntu15_amd64.deb - docker stop ubuntu15_build - docker rm ubuntu15_build +binaries/proxysql_${CURVER}-dbg-ubuntu16_amd64.deb: + docker stop ubuntu16_build || true + docker rm ubuntu16_build || true + docker create --name ubuntu16_build renecannao/proxysql:build-ubuntu16 bash -c "while : ; do sleep 10 ; done" + docker start ubuntu16_build + docker exec ubuntu16_build bash -c "cd /opt; git clone -b v${CURVER} https://github.com/sysown/proxysql.git proxysql" + docker exec ubuntu16_build bash -c "cd /opt/proxysql; ${MAKE} clean && ${MAKE} -j 4 build_deps && ${MAKE} debug" + docker cp docker/images/proxysql/ubuntu-16.04-build/proxysql.ctl ubuntu16_build:/opt/proxysql/ + docker exec ubuntu16_build bash -c "cd /opt/proxysql; cp src/proxysql . ; equivs-build proxysql.ctl" + docker cp ubuntu16_build:/opt/proxysql/proxysql_${CURVER}_amd64.deb ./binaries/proxysql_${CURVER}-ubuntu16_amd64.deb + docker stop ubuntu16_build + docker rm ubuntu16_build binaries/proxysql_${CURVER}-dbg-debian7_amd64.deb: docker stop debian7_build || true diff --git a/doc/passwords.md b/doc/passwords.md new file mode 100644 index 000000000..9a543b4fa --- /dev/null +++ b/doc/passwords.md @@ -0,0 +1,100 @@ +# MySQL Passwords in ProxySQL + +ProxySQL is a protocol aware proxy. +Because ProxySQL performs routing based on traffic, when a client connects it cannot yet identify a destination HG, therefore ProxySQL needs to authenticate the client. +For this reason, it needs to have some information related to the password of the user: enough information to allow the authentication. + +ProxySQL also needs these information to later establish connections to backends, or issue `CHANGE_USER` within already established connections. + +The 3 layers configuration architecture applies also for users information. +ProxySQL stores users information in table `mysql_users`: +* an object `MySQL_Authentication()` is responsible to store these information at runtime; +* `main`.`mysql_users` is the in-memory database; +* `runtime`.`mysql_users` is the on-disk database. + +In `mysql_users` tables, both in-memory and on-disk, the credentials are stored in columns `username` and `password`. + +## Password formats + +Password can be stored in 2 formats in `mysql_users`.`password` , no matter if in-memory or on-disk: +* plain text +* hashed password + +Passwords in plain text are simple as that, very easy to read. If database and config file are kept in a safe location the security concern is limited, yet present. +Hashed passwords have the same format of the passwords in MySQL server, as stored into column `mysql`.`user`.`password`. + +ProxySQL considers a password starting with `*` has a hashed password. + +### Hashed passwords and authentication + +In MySQL and in ProxySQL, a hashed password is `SHA1(SHA1('clear_password'))` . +From a hashed password is not possible to derive a plain text password. +When a client connects to ProxySQL, this is able to authenticate it using the hashed password. +During the first client authentication, ProxySQL can derive a partially hashed password: `SHA1('clear_password')` . This information is internally stored at runtime and allows ProxySQL to connect to backends. + + +### How to input new passwords + +The Admin interface of ProxySQL does not have any `PASSWORD()` function. This means that: +* passwords are stored in the format they are inserted, either in plain text or hashed +* while inputting password in the Admin interface, it is not possible to derive an hashed password from a plain text password (yet you can run `SELECT PASSWORD('password')` in MySQL server and copy paste the result) + + +### Variable `admin-hash_passwords` + +To facilitate the support of hashed passwords, ProxySQL v1.2.3 introduced a new global boolean variable, `admin-hash_password`, enabled by default. +When `admin-hash_password=true` , password are automatically hashed _at RUNTIME only_ when running `LOAD MYSQL USERS TO RUNTIME` . +Passwords in `mysql_users` tables are yet *not* automatically hashed. +Nonetheless, it is easily possible to hash the passwords in `mysql_users` table, both in-memory and on-disk. It is enough to copy users _from RUNTIME_, for example running `SAVE MYSQL USERS FROM RUNTIME` after `LOAD MYSQL USERS TO RUNTIME`, and then `SAVE MYSQL USERS TO DISK` (recommended). + +Here an example: +```sql +Admin> SELECT * FROM mysql_users; +Empty set (0.00 sec) + +Admin> INSERT INTO mysql_users(username,password) VALUES ('user1','password1'), ('user2','password2'); +Query OK, 2 rows affected (0.00 sec) + +Admin> SELECT username,password FROM mysql_users; ++----------+-----------+ +| username | password | ++----------+-----------+ +| user1 | password1 | +| user2 | password2 | ++----------+-----------+ +2 rows in set (0.00 sec) + +Admin> LOAD MYSQL USERS TO RUNTIME; +Query OK, 0 rows affected (0.00 sec) + +Admin> SELECT username,password FROM mysql_users; ++----------+-----------+ +| username | password | ++----------+-----------+ +| user1 | password1 | +| user2 | password2 | ++----------+-----------+ +2 rows in set (0.00 sec) +``` + +At this stage, passwords are hashed at runtime, but still not hashed on `mysql_users`. To hash them also on `mysql_users` : + +```sql +Admin> SAVE MYSQL USERS FROM RUNTIME; +Query OK, 0 rows affected (0.00 sec) + +Admin> SELECT username,password FROM mysql_users; ++----------+-------------------------------------------+ +| username | password | ++----------+-------------------------------------------+ +| user1 | *668425423DB5193AF921380129F465A6425216D0 | +| user2 | *DC52755F3C09F5923046BD42AFA76BD1D80DF2E9 | ++----------+-------------------------------------------+ +2 rows in set (0.00 sec) +``` + +The hashed password can now be saved to disk running `SAVE MYSQL USERS TO DISK` . + + +**Note**: `admin-hash_passwords` is an `admin-` variable, not a `mysql-` variable. This because it affects the behaviour of Admin. +This details is important because to apply changes in `admin-hash_passwords` you need to run `LOAD ADMIN VARIABLES TO RUNTIME` and **not** `LOAD MYSQL VARIABLES TO RUNTIME` diff --git a/docker/images/proxysql/centos67-build/proxysql.spec b/docker/images/proxysql/centos67-build/proxysql.spec index 482c71de8..694210102 100644 --- a/docker/images/proxysql/centos67-build/proxysql.spec +++ b/docker/images/proxysql/centos67-build/proxysql.spec @@ -7,7 +7,7 @@ Summary: A high-performance MySQL proxy Name: proxysql -Version: 1.2.2 +Version: 1.2.3 Release: 1 License: GPL+ Group: Development/Tools diff --git a/docker/images/proxysql/centos7-build/proxysql.spec b/docker/images/proxysql/centos7-build/proxysql.spec index 482c71de8..694210102 100644 --- a/docker/images/proxysql/centos7-build/proxysql.spec +++ b/docker/images/proxysql/centos7-build/proxysql.spec @@ -7,7 +7,7 @@ Summary: A high-performance MySQL proxy Name: proxysql -Version: 1.2.2 +Version: 1.2.3 Release: 1 License: GPL+ Group: Development/Tools diff --git a/docker/images/proxysql/debian-7.8-build/proxysql.ctl b/docker/images/proxysql/debian-7.8-build/proxysql.ctl index 5c86af112..8475d93a5 100644 --- a/docker/images/proxysql/debian-7.8-build/proxysql.ctl +++ b/docker/images/proxysql/debian-7.8-build/proxysql.ctl @@ -4,7 +4,7 @@ Homepage: http://www.proxysql.com Standards-Version: 3.9.2 Package: proxysql -Version: 1.2.2 +Version: 1.2.3 Maintainer: Rene Cannao Architecture: amd64 # Changelog: CHANGELOG.md diff --git a/docker/images/proxysql/debian-8.2-build/proxysql.ctl b/docker/images/proxysql/debian-8.2-build/proxysql.ctl index 5c86af112..8475d93a5 100644 --- a/docker/images/proxysql/debian-8.2-build/proxysql.ctl +++ b/docker/images/proxysql/debian-8.2-build/proxysql.ctl @@ -4,7 +4,7 @@ Homepage: http://www.proxysql.com Standards-Version: 3.9.2 Package: proxysql -Version: 1.2.2 +Version: 1.2.3 Maintainer: Rene Cannao Architecture: amd64 # Changelog: CHANGELOG.md diff --git a/docker/images/proxysql/fedora24-build/proxysql.spec b/docker/images/proxysql/fedora24-build/proxysql.spec new file mode 100644 index 000000000..694210102 --- /dev/null +++ b/docker/images/proxysql/fedora24-build/proxysql.spec @@ -0,0 +1,66 @@ +# Don't try fancy stuff like debuginfo, which is useless on binary-only +# packages. Don't strip binary too +# Be sure buildpolicy set to do nothing +%define __spec_install_post %{nil} +%define debug_package %{nil} +%define __os_install_post %{_dbpath}/brp-compress + +Summary: A high-performance MySQL proxy +Name: proxysql +Version: 1.2.3 +Release: 1 +License: GPL+ +Group: Development/Tools +SOURCE0 : %{name}-%{version}.tar.gz +URL: http://www.proxysql.com/ + +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root + +%description +%{summary} + +%prep +%setup -q + +%build +# Empty section. + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot} + +# in builddir +cp -a * %{buildroot} + +%clean +rm -rf %{buildroot} + +%post +mkdir /var/run/%{name} +chkconfig --add %{name} + +%postun +rm -rf /var/run/%{name} +chkconfig --del %{name} + +%files +%defattr(-,root,root,-) +%config(noreplace) %{_sysconfdir}/%{name}.cnf +%{_bindir}/* +%{_sysconfdir}/init.d/%{name} +/usr/share/proxysql/tools/proxysql_galera_checker.sh +/usr/share/proxysql/tools/proxysql_galera_writer.pl + +%changelog +* Fri Sep 2 2016 Rene Cannao 1.2.2 +- Second stable release of 1.2 +* Tue Aug 2 2016 Rene Cannao 1.2.1 +- First stable release of 1.2 +* Mon Mar 14 2016 Rene Cannao 1.2.0 +- First testing release of 1.2 +* Sat Mar 11 2016 Rene Cannao 1.1.2 +- Upgraded to release 1.1.2 +* Sat Oct 31 2015 Rene Cannao 1.0.1 +- Compiles 1.0.1 +* Wed Sep 9 2015 Andrei Ismail 0.2 +- Added support for automatic packaging on Ubuntu 14.04 and CentOS 7. diff --git a/docker/images/proxysql/fedora24-build/rpmmacros b/docker/images/proxysql/fedora24-build/rpmmacros new file mode 100644 index 000000000..a1d0f32f0 --- /dev/null +++ b/docker/images/proxysql/fedora24-build/rpmmacros @@ -0,0 +1,2 @@ +%_topdir %(echo $HOME)/rpmbuild +%_tmppath %{_topdir}/tmp \ No newline at end of file diff --git a/docker/images/proxysql/ubuntu-12.04-build/proxysql.ctl b/docker/images/proxysql/ubuntu-12.04-build/proxysql.ctl index 5c86af112..8475d93a5 100644 --- a/docker/images/proxysql/ubuntu-12.04-build/proxysql.ctl +++ b/docker/images/proxysql/ubuntu-12.04-build/proxysql.ctl @@ -4,7 +4,7 @@ Homepage: http://www.proxysql.com Standards-Version: 3.9.2 Package: proxysql -Version: 1.2.2 +Version: 1.2.3 Maintainer: Rene Cannao Architecture: amd64 # Changelog: CHANGELOG.md diff --git a/docker/images/proxysql/ubuntu-14.04-build/proxysql.ctl b/docker/images/proxysql/ubuntu-14.04-build/proxysql.ctl index 5c86af112..8475d93a5 100644 --- a/docker/images/proxysql/ubuntu-14.04-build/proxysql.ctl +++ b/docker/images/proxysql/ubuntu-14.04-build/proxysql.ctl @@ -4,7 +4,7 @@ Homepage: http://www.proxysql.com Standards-Version: 3.9.2 Package: proxysql -Version: 1.2.2 +Version: 1.2.3 Maintainer: Rene Cannao Architecture: amd64 # Changelog: CHANGELOG.md diff --git a/docker/images/proxysql/ubuntu-15.10-build/proxysql.ctl b/docker/images/proxysql/ubuntu-15.10-build/proxysql.ctl index 5c86af112..8475d93a5 100644 --- a/docker/images/proxysql/ubuntu-15.10-build/proxysql.ctl +++ b/docker/images/proxysql/ubuntu-15.10-build/proxysql.ctl @@ -4,7 +4,7 @@ Homepage: http://www.proxysql.com Standards-Version: 3.9.2 Package: proxysql -Version: 1.2.2 +Version: 1.2.3 Maintainer: Rene Cannao Architecture: amd64 # Changelog: CHANGELOG.md diff --git a/docker/images/proxysql/ubuntu-16.04-build/proxysql.ctl b/docker/images/proxysql/ubuntu-16.04-build/proxysql.ctl new file mode 100644 index 000000000..8475d93a5 --- /dev/null +++ b/docker/images/proxysql/ubuntu-16.04-build/proxysql.ctl @@ -0,0 +1,24 @@ +Section: misc +Priority: optional +Homepage: http://www.proxysql.com +Standards-Version: 3.9.2 + +Package: proxysql +Version: 1.2.3 +Maintainer: Rene Cannao +Architecture: amd64 +# Changelog: CHANGELOG.md +# Readme: README.md +Files: proxysql /usr/bin/ + etc/proxysql.cnf / + etc/init.d/proxysql / + tools/proxysql_galera_checker.sh /usr/share/proxysql/ + tools/proxysql_galera_writer.pl /usr/share/proxysql/ +Description: High performance MySQL proxy + ProxySQL is a fast, reliable MySQL proxy with advanced runtime configuration management (virtually no configuration change requires a restart). + . + It features query routing, query caching, query rewriting (for queries generated by ORMs, for example) and is most of the time a drop-in replacement for mysqld from the point of view of the application. It can be configured and remote controlled through an SQL-compatible admin interface. +File: postinst + #!/bin/sh -e + if [ ! -d /var/lib/proxysql ]; then mkdir /var/lib/proxysql ; fi + update-rc.d proxysql defaults diff --git a/include/proxysql.h b/include/proxysql.h index 1a79c3b8c..3397ef58d 100644 --- a/include/proxysql.h +++ b/include/proxysql.h @@ -99,7 +99,7 @@ #else #define DEB "" #endif /* DEBUG */ -#define PROXYSQL_VERSION "1.2.2" DEB +#define PROXYSQL_VERSION "1.2.3-RC" DEB #define PROXYSQL_CODENAME "Truls" #ifndef PROXYSQL_FUNC_DEFS diff --git a/include/proxysql_admin.h b/include/proxysql_admin.h index f1f645e4b..9f209e3ea 100644 --- a/include/proxysql_admin.h +++ b/include/proxysql_admin.h @@ -71,6 +71,7 @@ class ProxySQL_Admin { char *telnet_admin_ifaces; char *telnet_stats_ifaces; bool admin_read_only; + bool hash_passwords; char * admin_version; #ifdef DEBUG bool debug; @@ -147,7 +148,7 @@ class ProxySQL_Admin { void init_users(); void init_mysql_servers(); void init_mysql_query_rules(); - void save_mysql_users_runtime_to_database(); + void save_mysql_users_runtime_to_database(bool _runtime); void save_mysql_servers_runtime_to_database(bool); void admin_shutdown(); bool is_command(std::string); diff --git a/include/query_processor.h b/include/query_processor.h index 18f8340fd..37ee12a70 100644 --- a/include/query_processor.h +++ b/include/query_processor.h @@ -10,8 +10,10 @@ typedef std::unordered_map umap_query_digest; /* enum MYSQL_COM_QUERY_command { MYSQL_COM_QUERY_ALTER_TABLE, + MYSQL_COM_QUERY_ALTER_VIEW, MYSQL_COM_QUERY_ANALYZE_TABLE, MYSQL_COM_QUERY_BEGIN, + MYSQL_COM_QUERY_CALL, MYSQL_COM_QUERY_CHANGE_MASTER, MYSQL_COM_QUERY_COMMIT, MYSQL_COM_QUERY_CREATE_DATABASE, @@ -20,6 +22,8 @@ enum MYSQL_COM_QUERY_command { MYSQL_COM_QUERY_CREATE_TEMPORARY, MYSQL_COM_QUERY_CREATE_TRIGGER, MYSQL_COM_QUERY_CREATE_USER, + MYSQL_COM_QUERY_CREATE_VIEW, + MYSQL_COM_QUERY_DEALLOCATE, MYSQL_COM_QUERY_DELETE, MYSQL_COM_QUERY_DESCRIBE, MYSQL_COM_QUERY_DROP_DATABASE, @@ -27,7 +31,9 @@ enum MYSQL_COM_QUERY_command { MYSQL_COM_QUERY_DROP_TABLE, MYSQL_COM_QUERY_DROP_TRIGGER, MYSQL_COM_QUERY_DROP_USER, + MYSQL_COM_QUERY_DROP_VIEW, MYSQL_COM_QUERY_GRANT, + MYSQL_COM_QUERY_EXECUTE, MYSQL_COM_QUERY_EXPLAIN, MYSQL_COM_QUERY_FLUSH, MYSQL_COM_QUERY_INSERT, @@ -49,6 +55,7 @@ enum MYSQL_COM_QUERY_command { MYSQL_COM_QUERY_SET, MYSQL_COM_QUERY_SHOW_TABLE_STATUS, MYSQL_COM_QUERY_START_TRANSACTION, + MYSQL_COM_QUERY_TRUNCATE_TABLE, MYSQL_COM_QUERY_UNLOCK_TABLES, MYSQL_COM_QUERY_UPDATE, MYSQL_COM_QUERY_USE, diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 2db397b92..fe12b9ed8 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -628,7 +628,18 @@ bool MySQL_Session::handler_special_queries(PtrSize_t *pkt) { free(unstripped); return true; } - + if ( (pkt->size == 18) && (strncasecmp((char *)"SHOW WARNINGS",(char *)pkt->ptr+5,13)==0) ) { + SQLite3_result * resultset=new SQLite3_result(3); + resultset->add_column_definition(SQLITE_TEXT,"Level"); + resultset->add_column_definition(SQLITE_TEXT,"Code"); + resultset->add_column_definition(SQLITE_TEXT,"Message"); + SQLite3_to_MySQL(resultset, NULL, 0, &client_myds->myprot); + delete resultset; + client_myds->DSS=STATE_SLEEP; + status=WAITING_CLIENT_DATA; + l_free(pkt->size,pkt->ptr); + return true; + } return false; } diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index ee774664f..e81565133 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -54,6 +54,21 @@ char *s_strdup(char *s) { return ret; } + +static char *sha1_pass_hex(char *sha1_pass) { // copied from MySQL_Protocol.cpp + if (sha1_pass==NULL) return NULL; + char *buff=(char *)malloc(SHA_DIGEST_LENGTH*2+2); + buff[0]='*'; + buff[SHA_DIGEST_LENGTH*2+1]='\0'; + int i; + uint8_t a; + for (i=0;i= 0) NOT NULL DEFAULT 1 , compression INT CHECK (compression >=0 AND compression <= 102400) NOT NULL DEFAULT 0 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 1000 , max_replication_lag INT CHECK (max_replication_lag >= 0 AND max_replication_lag <= 126144000) NOT NULL DEFAULT 0 , use_ssl INT CHECK (use_ssl IN(0,1)) NOT NULL DEFAULT 0 , max_latency_ms INT UNSIGNED CHECK (max_latency_ms>=0) NOT NULL DEFAULT 0 , comment VARCHAR NOT NULL DEFAULT '' , PRIMARY KEY (hostgroup_id, hostname, port) )" #define ADMIN_SQLITE_TABLE_MYSQL_USERS "CREATE TABLE mysql_users (username VARCHAR NOT NULL , password VARCHAR , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1 , use_ssl INT CHECK (use_ssl IN (0,1)) NOT NULL DEFAULT 0 , default_hostgroup INT NOT NULL DEFAULT 0 , default_schema VARCHAR , schema_locked INT CHECK (schema_locked IN (0,1)) NOT NULL DEFAULT 0 , transaction_persistent INT CHECK (transaction_persistent IN (0,1)) NOT NULL DEFAULT 0 , fast_forward INT CHECK (fast_forward IN (0,1)) NOT NULL DEFAULT 0 , backend INT CHECK (backend IN (0,1)) NOT NULL DEFAULT 1 , frontend INT CHECK (frontend IN (0,1)) NOT NULL DEFAULT 1 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000 , PRIMARY KEY (username, backend) , UNIQUE (username, frontend))" + +#define ADMIN_SQLITE_RUNTIME_MYSQL_USERS "CREATE TABLE runtime_mysql_users (username VARCHAR NOT NULL , password VARCHAR , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1 , use_ssl INT CHECK (use_ssl IN (0,1)) NOT NULL DEFAULT 0 , default_hostgroup INT NOT NULL DEFAULT 0 , default_schema VARCHAR , schema_locked INT CHECK (schema_locked IN (0,1)) NOT NULL DEFAULT 0 , transaction_persistent INT CHECK (transaction_persistent IN (0,1)) NOT NULL DEFAULT 0 , fast_forward INT CHECK (fast_forward IN (0,1)) NOT NULL DEFAULT 0 , backend INT CHECK (backend IN (0,1)) NOT NULL DEFAULT 1 , frontend INT CHECK (frontend IN (0,1)) NOT NULL DEFAULT 1 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000 , PRIMARY KEY (username, backend) , UNIQUE (username, frontend))" + #define ADMIN_SQLITE_TABLE_MYSQL_QUERY_RULES "CREATE TABLE mysql_query_rules (rule_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 0 , username VARCHAR , schemaname VARCHAR , flagIN INT NOT NULL DEFAULT 0 , client_addr VARCHAR , proxy_addr VARCHAR , proxy_port INT , digest VARCHAR , match_digest VARCHAR , match_pattern VARCHAR , negate_match_pattern INT CHECK (negate_match_pattern IN (0,1)) NOT NULL DEFAULT 0 , flagOUT INT , replace_pattern VARCHAR , destination_hostgroup INT DEFAULT NULL , cache_ttl INT CHECK(cache_ttl > 0) , reconnect INT CHECK (reconnect IN (0,1)) DEFAULT NULL , timeout INT UNSIGNED , retries INT CHECK (retries>=0 AND retries <=1000) , delay INT UNSIGNED , mirror_flagOUT INT UNSIGNED , mirror_hostgroup INT UNSIGNED , error_msg VARCHAR , log INT CHECK (log IN (0,1)) , apply INT CHECK(apply IN (0,1)) NOT NULL DEFAULT 0 , comment VARCHAR)" // mysql_query_rules in v1.1.0 @@ -167,6 +185,7 @@ static char * admin_variables_names[]= { (char *)"telnet_stats_ifaces", (char *)"refresh_interval", (char *)"read_only", + (char *)"hash_passwords", (char *)"version", #ifdef DEBUG (char *)"debug", @@ -826,7 +845,7 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query ) { proxy_info("Received %s command\n", query_no_space); ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; - SPA->save_mysql_users_runtime_to_database(); + SPA->save_mysql_users_runtime_to_database(false); proxy_debug(PROXY_DEBUG_ADMIN, 4, "Saved mysql users from RUNTIME\n"); SPA->send_MySQL_OK(&sess->client_myds->myprot, NULL); return false; @@ -1207,6 +1226,7 @@ void ProxySQL_Admin::GenericRefreshStatistics(const char *query_no_space, unsign bool dump_global_variables=false; bool runtime_scheduler=false; + bool runtime_mysql_users=false; bool runtime_mysql_servers=false; bool runtime_mysql_query_rules=false; @@ -1239,6 +1259,9 @@ void ProxySQL_Admin::GenericRefreshStatistics(const char *query_no_space, unsign ) { runtime_mysql_servers=true; refresh=true; } + if (strstr(query_no_space,"runtime_mysql_users")) { + runtime_mysql_users=true; refresh=true; + } if (strstr(query_no_space,"runtime_mysql_query_rules")) { runtime_mysql_query_rules=true; refresh=true; } @@ -1276,6 +1299,9 @@ void ProxySQL_Admin::GenericRefreshStatistics(const char *query_no_space, unsign save_mysql_servers_runtime_to_database(true); mysql_servers_wrunlock(); } + if (runtime_mysql_users) { + save_mysql_users_runtime_to_database(true); + } if (runtime_mysql_query_rules) { save_mysql_query_rules_from_runtime(true); } @@ -2389,6 +2415,7 @@ ProxySQL_Admin::ProxySQL_Admin() { //variables.telnet_admin_ifaces=strdup("127.0.0.1:6030"); //variables.telnet_stats_ifaces=strdup("127.0.0.1:6031"); variables.refresh_interval=2000; + variables.hash_passwords=true; // issue #676 variables.admin_read_only=false; // by default, the admin interface accepts writes variables.admin_version=(char *)PROXYSQL_VERSION; #ifdef DEBUG @@ -2478,6 +2505,7 @@ bool ProxySQL_Admin::init() { insert_into_tables_defs(tables_defs_admin,"mysql_servers", ADMIN_SQLITE_TABLE_MYSQL_SERVERS); insert_into_tables_defs(tables_defs_admin,"runtime_mysql_servers", ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_SERVERS); insert_into_tables_defs(tables_defs_admin,"mysql_users", ADMIN_SQLITE_TABLE_MYSQL_USERS); + insert_into_tables_defs(tables_defs_admin,"runtime_mysql_users", ADMIN_SQLITE_RUNTIME_MYSQL_USERS); insert_into_tables_defs(tables_defs_admin,"runtime_mysql_replication_hostgroups", ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_REPLICATION_HOSTGROUPS); insert_into_tables_defs(tables_defs_admin,"mysql_replication_hostgroups", ADMIN_SQLITE_TABLE_MYSQL_REPLICATION_HOSTGROUPS); insert_into_tables_defs(tables_defs_admin,"mysql_query_rules", ADMIN_SQLITE_TABLE_MYSQL_QUERY_RULES); @@ -2920,6 +2948,9 @@ char * ProxySQL_Admin::get_variable(char *name) { if (!strcasecmp(name,"read_only")) { return strdup((variables.admin_read_only ? "true" : "false")); } + if (!strcasecmp(name,"hash_passwords")) { + return strdup((variables.hash_passwords ? "true" : "false")); + } #ifdef DEBUG if (!strcasecmp(name,"debug")) { return strdup((variables.debug ? "true" : "false")); @@ -3095,6 +3126,17 @@ bool ProxySQL_Admin::set_variable(char *name, char *value) { // this is the pub return false; } } + if (!strcasecmp(name,"hash_passwords")) { + if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) { + variables.hash_passwords=true; + return true; + } + if (strcasecmp(value,"false")==0 || strcasecmp(value,"0")==0) { + variables.hash_passwords=false; + return true; + } + return false; + } if (!strcasecmp(name,"read_only")) { if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) { variables.admin_read_only=true; @@ -3772,9 +3814,38 @@ void ProxySQL_Admin::__add_active_users(enum cred_username_type usertype) { } else { for (std::vector::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { SQLite3_row *r=*it; + char *password=NULL; + if (variables.hash_passwords) { // We must use hashed password. See issue #676 + // Admin needs to hash the password + if (r->fields[1] && strlen(r->fields[1])) { + if (r->fields[1][0]=='*') { // the password is already hashed + password=strdup(r->fields[1]); + } else { // we must hash it + uint8 hash_stage1[SHA_DIGEST_LENGTH]; + uint8 hash_stage2[SHA_DIGEST_LENGTH]; + SHA_CTX sha1_context; + SHA1_Init(&sha1_context); + SHA1_Update(&sha1_context, r->fields[1], strlen(r->fields[1])); + SHA1_Final(hash_stage1, &sha1_context); + SHA1_Init(&sha1_context); + SHA1_Update(&sha1_context,hash_stage1,SHA_DIGEST_LENGTH); + SHA1_Final(hash_stage2, &sha1_context); + password=sha1_pass_hex((char *)hash_stage2); // note that sha1_pass_hex() returns a new buffer + } + } else { + password=strdup((char *)""); // we also generate a new string if hash_passwords is set + } + } else { + if (r->fields[1]) { + password=r->fields[1]; + } else { + password=(char *)""; + } + } GloMyAuth->add( r->fields[0], // username - (r->fields[1]==NULL ? (char *)"" : r->fields[1]), //password + //(r->fields[1]==NULL ? (char *)"" : r->fields[1]), //password + password, // before #676, wewere always passing the password. Now it is possible that the password can be hashed usertype, // backend/frontend (strcmp(r->fields[2],"1")==0 ? true : false) , // use_ssl atoi(r->fields[3]), // default_hostgroup @@ -3785,6 +3856,9 @@ void ProxySQL_Admin::__add_active_users(enum cred_username_type usertype) { (strcmp(r->fields[7],"1")==0 ? true : false), // fast_forward ( atoi(r->fields[8])>0 ? atoi(r->fields[8]) : 0) // max_connections ); + if (variables.hash_passwords) { + free(password); // because we always generate a new string + } } } // if (error) free(error); @@ -3793,7 +3867,7 @@ void ProxySQL_Admin::__add_active_users(enum cred_username_type usertype) { } -void ProxySQL_Admin::save_mysql_users_runtime_to_database() { +void ProxySQL_Admin::save_mysql_users_runtime_to_database(bool _runtime) { /* char *error=NULL; int cols=0; @@ -3808,32 +3882,48 @@ void ProxySQL_Admin::save_mysql_users_runtime_to_database() { } if(resultset) delete resultset; */ - char *qd=(char *)"UPDATE mysql_users SET active=0"; - proxy_debug(PROXY_DEBUG_ADMIN, 4, "%s\n", qd); - admindb->execute(qd); + char *query=NULL; + if (_runtime) { + query=(char *)"DELETE FROM main.runtime_mysql_users"; + admindb->execute(query); + } else { + char *qd=(char *)"UPDATE mysql_users SET active=0"; + proxy_debug(PROXY_DEBUG_ADMIN, 4, "%s\n", qd); + admindb->execute(qd); + } account_details_t **ads=NULL; int num_users; int i; char *qf=(char *)"REPLACE INTO mysql_users(username,password,active,use_ssl,default_hostgroup,default_schema,schema_locked,transaction_persistent,fast_forward,backend,frontend,max_connections) VALUES(\"%s\",\"%s\",1,%d,%d,\"%s\",%d,%d,%d,COALESCE((SELECT backend FROM mysql_users WHERE username=\"%s\" AND frontend=1),0),1,%d)"; char *qb=(char *)"REPLACE INTO mysql_users(username,password,active,use_ssl,default_hostgroup,default_schema,schema_locked,transaction_persistent,fast_forward,backend,frontend,max_connections) VALUES(\"%s\",\"%s\",1,%d,%d,\"%s\",%d,%d,%d,1,COALESCE((SELECT frontend FROM mysql_users WHERE username=\"%s\" AND backend=1),0),%d)"; + char *qfr=(char *)"REPLACE INTO runtime_mysql_users(username,password,active,use_ssl,default_hostgroup,default_schema,schema_locked,transaction_persistent,fast_forward,backend,frontend,max_connections) VALUES(\"%s\",\"%s\",1,%d,%d,\"%s\",%d,%d,%d,COALESCE((SELECT backend FROM runtime_mysql_users WHERE username=\"%s\" AND frontend=1),0),1,%d)"; + char *qbr=(char *)"REPLACE INTO runtime_mysql_users(username,password,active,use_ssl,default_hostgroup,default_schema,schema_locked,transaction_persistent,fast_forward,backend,frontend,max_connections) VALUES(\"%s\",\"%s\",1,%d,%d,\"%s\",%d,%d,%d,1,COALESCE((SELECT frontend FROM runtime_mysql_users WHERE username=\"%s\" AND backend=1),0),%d)"; num_users=GloMyAuth->dump_all_users(&ads); if (num_users==0) return; for (i=0; iusername, ads[i]->default_hostgroup); account_details_t *ad=ads[i]; if (ads[i]->default_hostgroup >= 0) { - char *query; - char *q; - if (ad->__frontend) { - q=qf; - } else { - q=qb; + char *q=NULL; + if (_runtime==false) { + if (ad->__frontend) { + q=qf; + } else { + q=qb; + } + } else { // _runtime==true + if (ad->__frontend) { + q=qfr; + } else { + q=qbr; + } } query=(char *)malloc(strlen(q)+strlen(ad->username)*2+strlen(ad->password)+strlen(ad->default_schema)+256); sprintf(query, q, ad->username, ad->password, ad->use_ssl, ad->default_hostgroup, ad->default_schema, ad->schema_locked, ad->transaction_persistent, ad->fast_forward, ad->username, ad->max_connections); //fprintf(stderr,"%s\n",query); proxy_debug(PROXY_DEBUG_ADMIN, 4, "%s\n", query); admindb->execute(query); + free(query); } free(ad->username); free(ad->password); diff --git a/lib/Query_Cache.cpp b/lib/Query_Cache.cpp index 06eacd5d9..40a3e1689 100644 --- a/lib/Query_Cache.cpp +++ b/lib/Query_Cache.cpp @@ -27,7 +27,7 @@ #else #define DEB "" #endif /* DEBUG */ -#define QUERY_CACHE_VERSION "1.2.0817" DEB +#define QUERY_CACHE_VERSION "1.2.0905" DEB extern MySQL_Threads_Handler *GloMTH; @@ -47,7 +47,7 @@ class KV_BtreeArray { KV_BtreeArray(); ~KV_BtreeArray(); uint64_t get_data_size(); - void purge_some(unsigned long long); + void purge_some(unsigned long long, bool); int cnt(); bool replace(uint64_t key, QC_entry_t *entry); QC_entry_t *lookup(uint64_t key); @@ -122,30 +122,75 @@ KV_BtreeArray::~KV_BtreeArray() { uint64_t KV_BtreeArray::get_data_size() { - uint64_t r = __sync_fetch_and_add(&Glo_num_entries,0) * (sizeof(QC_entry_t)+sizeof(QC_entry_t *)*2+sizeof(uint64_t)*2) + __sync_fetch_and_add(&Glo_size_values,0) ; + uint64_t r = __sync_fetch_and_add(&Glo_num_entries,0) * (sizeof(QC_entry_t)+sizeof(QC_entry_t *)*2+sizeof(uint64_t)*2); // + __sync_fetch_and_add(&Glo_size_values,0) ; return r; }; -void KV_BtreeArray::purge_some(unsigned long long QCnow_ms) { +void KV_BtreeArray::purge_some(unsigned long long QCnow_ms, bool aggressive) { uint64_t ret=0, i, _size=0; QC_entry_t *qce; + unsigned long long access_ms_min=0; + unsigned long long access_ms_max=0; spin_rdlock(&lock); for (i=0; ilen;i++) { qce=(QC_entry_t *)ptrArray->index(i); - if (qce->expire_ms==EXPIRE_DROPIT || qce->expire_mslength; + if (aggressive) { // we have been asked to do aggressive purging + if (access_ms_min==0) { + access_ms_min = qce->access_ms; + } else { + if (access_ms_min > qce->access_ms) { + access_ms_min = qce->access_ms; + } + } + if (access_ms_max==0) { + access_ms_max = qce->access_ms; + } else { + if (access_ms_max < qce->access_ms) { + access_ms_max = qce->access_ms; + } + } + } else { // no aggresssive purging , legacy algorithm + if (qce->expire_ms==EXPIRE_DROPIT || qce->expire_mslength; + } } } freeable_memory=_size; spin_rdunlock(&lock); - if ( (freeable_memory + ret * (sizeof(QC_entry_t)+sizeof(QC_entry_t *)*2+sizeof(uint64_t)*2) ) > get_data_size()*0.01) { + bool cond_freeable_memory=false; + if (aggressive==false) { + uint64_t total_freeable_memory=0; + total_freeable_memory=freeable_memory + ret * (sizeof(QC_entry_t)+sizeof(QC_entry_t *)*2+sizeof(uint64_t)*2); + if ( total_freeable_memory > get_data_size()*0.01 ) { + cond_freeable_memory=true; // there is memory that can be freed + } + } + //if ( freeable_memory + ret * (sizeof(QC_entry_t) > get_data_size()*0.01) { + if ( aggressive || cond_freeable_memory ) { uint64_t removed_entries=0; uint64_t freed_memory=0; + unsigned long long access_ms_lower_mark=0; + if (aggressive) { + access_ms_lower_mark=access_ms_min+(access_ms_max-access_ms_min)*0.1; // hardcoded for now. Remove the entries with access time in the 10% range closest to access_ms_min + } spin_wrlock(&lock); for (i=0; ilen;i++) { qce=(QC_entry_t *)ptrArray->index(i); - if ((qce->expire_ms==EXPIRE_DROPIT || qce->expire_msref_count,0)<=1)) { + bool drop_entry=false; + if (__sync_fetch_and_add(&qce->ref_count,0)<=1) { // currently not in use + if (qce->expire_ms==EXPIRE_DROPIT || qce->expire_msaccess_ms < access_ms_lower_mark) { + drop_entry=true; + } + } + } + } + if (drop_entry) { qce=(QC_entry_t *)ptrArray->remove_index_fast(i); btree::btree_map::iterator lookup; @@ -242,6 +287,7 @@ uint64_t Query_Cache::get_data_size_total() { for (i=0; iget_data_size(); } + r += __sync_fetch_and_add(&Glo_size_values,0); return r; }; @@ -364,9 +410,10 @@ void * Query_Cache::purgeHash_thread(void *) { max_memory_size=mysql_thread___query_cache_size_MB*1024*1024; } } - if (current_used_memory_pct() < purge_threshold_pct_min ) continue; + unsigned int curr_pct=current_used_memory_pct(); + if (curr_pct < purge_threshold_pct_min ) continue; for (i=0; ipurge_some(QCnow_ms); + KVs[i]->purge_some(QCnow_ms, (curr_pct > purge_threshold_pct_max)); } } delete mysql_thr; diff --git a/lib/Query_Processor.cpp b/lib/Query_Processor.cpp index 3d2456b25..02178c1c6 100644 --- a/lib/Query_Processor.cpp +++ b/lib/Query_Processor.cpp @@ -298,8 +298,10 @@ Query_Processor::Query_Processor() { for (int i=0; i