程序有两个线程,每个线程都有lock table 语句,但是两个线程仍然能访问相同的字段,而且在程序运行过程中,通过mysql控制台仍然能够update该字段。但是两个线程运行结束(该程序的运行窗口没有关闭),此时通过mysql控制台进行update,则阻塞,只有当关闭该程序运行窗口时,阻塞解除,可以进行update了。不知道是怎么回事?难道在多线程中,不能用lock table语句锁表?
解决方案 »
- 请问Mysql中有类似merge into这种函数吗?
- Icc编译MySQL性能调研
- 各位大神看一看吧,这个错误我调一天了。。。SQL的修改语句
- php+mysql报错
- 请教关于时间计算的问题
- 同一天加總問題?
- 求将SQL SERVER语句转换为MYSQL语句的问题,急救,50分,在线急等。
- 在mysql里我用root用户建了个mydb数据库,请问我怎样可以新建一个用户,并且使该用户拥有新数据库mydb的表有类似develop的权限.
- mysql长什么样啊亲爱的大神们!
- mac终端操作mysql向表格插入汉字第一次成功第二次乱码,char1列添加一个汉字出现错误
- 定义载入时间
- Mysql的MyIsam COUNT问题
估计是你的线程的代码没写正确。
MYSQL命令行再操作,产生SESSION2S1对表进行LOCK TABLE的时候,在表上加的是X锁,级别最高。这时候S2想在UPDATE的时候再加X锁,就必须等待前面的X锁释放。才能加上X锁。在你的程序进行LOCK TABLE后,再执行UNLOCK TABLES,那么就会释放X锁。
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <CString>
#include <sql.h>
#include <sqlext.h>
#include <odbcss.h>
using namespace std;CRITICAL_SECTION Section;
SQLHENV henv1 = 0;
SQLHENV henv2= 0;
SQLHDBC hdbc1 = 0;
SQLHDBC hdbc2 = 0;
int ConnectDB(SQLHENV &henv,SQLHDBC &hdbc)
{
RETCODE retcode; //signed short
retcode = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);//申请环境句柄
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
char szDSN[10] = "test_db"; //一个合法的DSN Name
char szUID[5] = "root"; //用户名
char szAuthStr[5] = "root";
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);//申请连接句柄
retcode = SQLConnect(hdbc, (SQLCHAR *)szDSN, (SWORD)strlen(szDSN),
(SQLCHAR *)szUID, (SWORD)strlen(szUID),
(SQLCHAR *)szAuthStr,(SWORD)strlen(szAuthStr)); if((retcode != SQL_SUCCESS)&&(retcode != SQL_SUCCESS_WITH_INFO))
printf("Connection Error\n");
else
printf("Connection Successfully\n");
return retcode;
}
DWORD WINAPI ThreadOne(LPVOID param);
DWORD WINAPI ThreadTwo(LPVOID param); int main(int argc, char* argv[])
{
if(ConnectDB(henv1,hdbc1))
cout<<"Connect failed!"<<endl;
else
cout<<"Connect successful!"<<endl; if(ConnectDB(henv2,hdbc2))
cout<<"Connect failed!"<<endl;
else
cout<<"Connect successful!"<<endl; HANDLE handl1;
HANDLE handl2;
handl1=CreateThread(NULL,0,ThreadOne,NULL,0,NULL);
handl2=CreateThread(NULL,0,ThreadTwo,NULL,0,NULL);
CloseHandle(handl1);
CloseHandle(handl2); InitializeCriticalSection(&Section);
Sleep(40000);
DeleteCriticalSection(&Section); getchar();
return 0;
} DWORD WINAPI ThreadOne(LPVOID param){
SQLHSTMT hstmt = 0;
RETCODE retcode;
RETCODE retcode1;
SQLTCHAR sql[60]={0};
SQLTCHAR sql1[60]={0};
SQLINTEGER number;
SQLINTEGER cbKey;
while(TRUE)
{
strcpy((char *)sql,"lock tables test write");
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt);
retcode = SQLExecDirect(hstmt,sql,SQL_NTS); strcpy((char *)sql,"select number from test where ID = '1002'");
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt);
retcode = SQLExecDirect(hstmt,sql,SQL_NTS);
retcode = SQLFetch(hstmt);
SQLGetData(hstmt,1,SQL_C_SLONG,&number,0,&cbKey); if (number>0)
{ strcpy((char *)sql,"select number from test where ID = '1002'");
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt);
retcode = SQLExecDirect(hstmt,sql,SQL_NTS);
retcode = SQLFetch(hstmt);
SQLGetData(hstmt,1,SQL_C_SLONG,&number,0,&cbKey);
Sleep(10); cout<<"thread2:"<<number<<endl; strcpy((char *)sql,"update test set number=number-1 where ID = '1002'");
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt);
retcode = SQLExecDirect(hstmt,sql,SQL_NTS);
}
else
break;
}
cout<<"thread 2 is running"<<endl; SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return 0;
}DWORD WINAPI ThreadTwo(LPVOID param){
SQLHSTMT hstmt = 0;
RETCODE retcode;
SQLTCHAR sql[60]={0};
SQLINTEGER number;
SQLINTEGER cbKey;
while(TRUE)
{
strcpy((char *)sql,"select number from test where ID = '1002'");
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc2, &hstmt);
retcode = SQLExecDirect(hstmt,sql,SQL_NTS);
retcode = SQLFetch(hstmt);
SQLGetData(hstmt,1,SQL_C_SLONG,&number,0,&cbKey); if (number>0)
{
strcpy((char *)sql,"select number from test where ID = '1002'");
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc2, &hstmt);
retcode = SQLExecDirect(hstmt,sql,SQL_NTS);
retcode = SQLFetch(hstmt);
SQLGetData(hstmt,1,SQL_C_SLONG,&number,0,&cbKey);
Sleep(10);
cout<<"thread3:"<<number<<endl; strcpy((char *)sql,"update test set number=number-1 where ID = '1002'");
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc2, &hstmt);
retcode = SQLExecDirect(hstmt,sql,SQL_NTS);
}
else
break;
}
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
return 0;
}
你要在线程2上也加lock table,那样才有效果。
在多线程中,不同的线程都修改同一个表,如何处理锁表呢?怎么测试呢?
有两个问题:
1. 每次获取连接之后,立即执行set AUTOCOMMIT = 0 (必须这样,否则调了lock ...之后,会立即释放锁)
2. 在进行了1之后,lock之后,线程退出之前,别忘了调用unlock多线程是个细心活儿:-)
set AUTOCOMMIT = 0 这个是做什么的的?
AUTOCOMMIT 这个变量是什么啊?
谢谢喽~
它的意思是禁止自动提交。
否则lock table write自动提交完,锁也就放掉了。
不过我的表类型是MyISAM类型,好像AUTOCOMMIT 变量在处理MyISAM表类型时不起作用。
其实我的主要目的就是多线程访问数据库(同一个表)时,①当一个线程正在写入数据时,其他线程不能写,也不能读。②当一个线程正在读入数据时,其他线程不能写,但能够读。
不知道这方面应该怎么做,或者有没有什么例子或者看看哪方面的书籍
O(∩_∩)O~我刚刚接触数据库~
这时,你不要借助于sql语句中的lock table之类的,
你要自己实现一套读写锁。建议有空看看Unix网络编程第二卷,--进程间通信