1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
#include "cmdline.h"
#include <mysql++.h>
#include <mysqld_error.h>
#include <iostream>
using namespace std;
// Bring in global holding the value given to the -m switch
extern int run_mode;
int
main(int argc, char *argv[])
{
// Get database access parameters from command line
mysqlpp::examples::CommandLine cmdline(argc, argv);
if (!cmdline) {
return 1;
}
// Check that the mode parameter was also given and it makes sense
const int run_mode = cmdline.run_mode();
if ((run_mode != 1) && (run_mode != 2)) {
cerr << argv[0] << " must be run with -m1 or -m2 as one of "
"its command-line arguments." << endl;
return 1;
}
mysqlpp::Connection con;
try {
// Establish the connection to the database server
mysqlpp::Connection con(mysqlpp::examples::db_name,
cmdline.server(), cmdline.user(), cmdline.pass());
// Start a transaction set. Transactions create mutex locks on
// modified rows, so if two programs both touch the same pair of
// rows but in opposite orders at the wrong time, one of the two
// programs will deadlock. The MySQL server knows how to detect
// this situation, and its error return causes MySQL++ to throw
// a BadQuery exception. The point of this example is that if
// you want to detect this problem, you would check the value of
// BadQuery::errnum(), not Connection::errnum(), because the
// transaction rollback process executes a query which succeeds,
// setting the MySQL C API's "last error number" value to 0.
// The exception object carries its own copy of the error number
// at the point the exception was thrown for this very reason.
mysqlpp::Query query = con.query();
mysqlpp::Transaction trans(con);
// Build and run the queries, with the order depending on the -m
// flag, so that a second copy of the program will deadlock if
// run while the first is waiting for Enter.
char dummy[100];
for (int i = 0; i < 2; ++i) {
int lock = run_mode + (run_mode == 1 ? i : -i);
cout << "Trying lock " << lock << "..." << endl;
query << "select * from deadlock_test" << lock <<
" where x = " << lock << " for update";
query.store();
cout << "Acquired lock " << lock << ". Press Enter to ";
cout << (i == 0 ? "try next lock" : "exit");
cout << ": " << flush;
cin.getline(dummy, sizeof(dummy));
}
}
catch (mysqlpp::BadQuery e) {
if (e.errnum() == ER_LOCK_DEADLOCK) {
cerr << "Transaction deadlock detected!" << endl;
cerr << "Connection::errnum = " << con.errnum() <<
", BadQuery::errnum = " << e.errnum() << endl;
}
else {
cerr << "Unexpected query error: " << e.what() << endl;
}
return 1;
}
catch (mysqlpp::Exception e) {
cerr << "General error: " << e.what() << endl;
return 1;
}
return 0;
}
|