WARNING !!!
Before you do anything, mysqldump the entire database or tarball /var/lib/mysql
If you are concerned about case sensitivity, you need to hunt down the usernames in a special way
I tried this little experiment
use test
DROP TABLE rolando;
CREATE TABLE rolando
(id int not null auto_increment,
name varchar(20),primary key (id));
INSERT INTO rolando (name) VALUES
('rolando'),('Rolando'),
('ROLANDO'),('ROLANDO'),
('rolando'),('rolando');
I loaded the sample data
mysql> use test
Database changed
mysql> DROP TABLE rolando;
Query OK, 0 rows affected (0.03 sec)
mysql> CREATE TABLE rolando
-> (id int not null auto_increment,
-> name varchar(20),primary key (id));
Query OK, 0 rows affected (0.07 sec)
mysql> INSERT INTO rolando (name) VALUES
-> ('rolando'),('Rolando'),
-> ('ROLANDO'),('ROLANDO'),
-> ('rolando'),('rolando');
Query OK, 6 rows affected (0.08 sec)
Records: 6 Duplicates: 0 Warnings: 0
I ran these queries (please note subtle differences)
mysql> SELECT name,COUNT(1) FROM rolando GROUP BY name;
+---------+----------+
| name | COUNT(1) |
+---------+----------+
| rolando | 6 |
+---------+----------+
1 row in set (0.00 sec)
mysql> SELECT name,MD5(name),COUNT(1) FROM rolando GROUP BY name,MD5(name);
+---------+----------------------------------+----------+
| name | MD5(name) | COUNT(1) |
+---------+----------------------------------+----------+
| ROLANDO | b3f7ba680fe83ab0b5174737e8d536a2 | 2 |
| Rolando | e0732d78dc135b8fcc33ec79bfa89d1f | 1 |
| rolando | e80d4ab77eb18a4ca350157fd487d7e2 | 3 |
+---------+----------------------------------+----------+
3 rows in set (0.00 sec)
mysql> SELECT name,MD5(name)=MD5(LOWER(name)) from rolando;
+---------+----------------------------+
| name | MD5(name)=MD5(LOWER(name)) |
+---------+----------------------------+
| rolando | 1 |
| Rolando | 0 |
| ROLANDO | 0 |
| ROLANDO | 0 |
| rolando | 1 |
| rolando | 1 |
+---------+----------------------------+
6 rows in set (0.00 sec)
mysql> SELECT name,COUNT(1) FROM rolando GROUP BY name;
+---------+----------+
| name | COUNT(1) |
+---------+----------+
| rolando | 6 |
+---------+----------+
1 row in set (0.00 sec)
mysql> SELECT name,(name LIKE lower(name)) like1,
-> (name = binary LOWER(name)) like2 FROM rolando;
+---------+-------+-------+
| name | like1 | like2 |
+---------+-------+-------+
| rolando | 1 | 1 |
| Rolando | 1 | 0 |
| ROLANDO | 1 | 0 |
| ROLANDO | 1 | 0 |
| rolando | 1 | 1 |
| rolando | 1 | 1 |
+---------+-------+-------+
6 rows in set (0.00 sec)
mysql>
Give this view of my experiment, a username with all uppercase or mixed case can be equal to an all lowercase UNLESS YOU USE BINARY
operator with the comparison
I do not think BINARY
can be applied to ON DELETE CASCADE
.
However, you could something like this: To delete all usernames that are lowercase only, try running one of the following:
DELETE FROM logins WHERE username = BINARY LOWER(username);
or
DELETE FROM logins WHERE MD5(username) = MD5(LOWER(username));
If you run this now, you might nix all usernames in the other tables. Run this instead
SET FOREIGN_KEY_CHECKS=0;
DELETE FROM logins WHERE username = BINARY LOWER(username);
or
SET FOREIGN_KEY_CHECKS=0;
DELETE FROM logins WHERE MD5(username) = MD5(LOWER(username));
You will have to go to all tables that have a username in it and execute
SET FOREIGN_KEY_CHECKS=0;
DELETE FROM <whatevertable1> WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP '^.*[A-Z].+$';
DELETE FROM <whatevertable2> WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP '^.*[A-Z].+$';
DELETE FROM <whatevertable3> WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP '^.*[A-Z].+$';
.
.
.
DELETE FROM <whatevertableN> WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP '^.*[A-Z].+$';
Since you have a ton of other tables, use the INFORMATION_SCHEMA to script it for you:
DELETE_SQLFILE=/root/SensitiveDelete.sql
MYSQL_CONN="-uroot -ppassword"
echo "SET FOREIGN_KEY_CHECKS=0;" > ${DELETE_SQLFILE}
mysql ${MYSQL_CONN} -ANe"SELECT CONCAT('DELETE FROM ',table_schema,'.',table_name,' WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP ''\^.*[A-Z].+$''\) FROM information_schema.columns WHERE column_name='user_name'" >> ${DELETE_SQLFILE}
cat ${DELETE_SQLFILE}
If the file is correct to you, run it in the mysql client like this
mysql ${MYSQL_CONN} -A < ${DELETE_SQLFILE}
Give it a Try !!!
Your process is sound. Putting the index on the date column will make it much faster for SQL Server to find the rows that it is looking for. Without the nonclustered index SQL Server will need to scan the production table every time you go to delete the rows. This means that SQL will need to load the entire table from disk each time the DELETE TOP 500 runs. Having (and using) the nonclustered index will be essential for getting this done quickly.
As for the memory setting, you'll want to set that to give SQL Server access to as much RAM as possible. You are correct, SQL Server will release RAM if other applications need it. The fact that you are seeing PAGEIOLATCH_EX and PAGEIOLATCH_SH waits tells me that you don't have enough RAM to keep the nonclustered index which you created in memory when combined with the other data which the system is using. Increasing the memory settings on the SQL Server will help this, provided that you have more memory in the server.
Those two wait types (PAGEIOLATCH_EX and PAGEIOLATCH_SH) tell us that you are waiting for the disk to respond to your request for more data to be loaded. The more data you can keep in memory the less data you'll need to read from the disk.
Best Answer
Specify to not use any creation SQL with --no-create-info
If you want to overwrite the records on reload of the mysqldump, just add --replace
I suggested --replace because REPLACE is a mechanical DELETE and INSERT.
Give it a Try !!!